package com.kehutong.contact.service.impl;

import com.kehutong.common.DoveClient;
import com.kehutong.common.constant.CommonConstant;
import com.kehutong.common.entity.Root;
import com.kehutong.common.enums.Gender;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.permission.UserLoginInfo;
import com.kehutong.common.util.SnowflakeIdUtils;
import com.kehutong.common.util.Token;
import com.kehutong.contact.entity.*;
import com.kehutong.contact.enums.*;
import com.kehutong.contact.service.ResidentAssetsService;
import com.kehutong.contact.service.ResidentService;
import com.kehutong.contact.util.ExcelUtil;
import com.kehutong.contact.util.FirstLetterUtil;
import com.kehutong.contact.util.ResidentTagUtil;
import com.kehutong.user.dao.ResidentUserDao;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.coraframework.authz.Subject;
import org.coraframework.authz.SubjectUtil;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.Condition;
import org.coraframework.orm.jdbc.execute.QueryCondition;
import org.coraframework.orm.jdbc.execute.entity.FindArray;
import org.coraframework.orm.jdbc.execute.entity.FindOne;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.orm.util.Enums;
import org.coraframework.util.EnumUtil;
import org.coraframework.util.Objects;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 住户服务处理实现
 *
 * @author liukl
 */
@WebService("/crm/resident/service")
public class ResidentServiceImpl implements ResidentService {
    private static final Logger logger = LoggerFactory.getLogger(ResidentServiceImpl.class);

    @Inject
    private JdbcSession jdbcSession;

    @Inject
    private DoveClient doveClient;

    @Inject
    private ResidentAssetsService residentAssetsService;

    @Inject
    private ResidentUserDao residentUserDao;

    /**
     * 远程调用测试方法
     *
     * @param p1
     * @param p2
     * @param p3
     * @return
     * @throws Exception
     */
    @ReqMapping("/executeTestClient")
    public String executeTestClient(Integer p1, Map<String, String> p2, Boolean p3) throws Exception {
        logger.info(p1.toString());
        logger.info(p2.toString());
        logger.info(p3.toString());
        return "1234";
    }

    private List<String> getUserId(String content) {
        if (Objects.isEmpty(content)) {
            return Collections.emptyList();
        }

        String[] userIdStr = content.split(",");
        List<String> userIds = new ArrayList<>();
        for (String uid : userIdStr) {
            if (Objects.nonEmpty(uid)) {
                userIds.add(uid);
            }
        }

        return userIds;
    }

    /***
     * 根据住户标志获取住户信息
     * @param id 住户标志
     * @return 住户对象
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentById")
    @Override
    public Resident getResidentById(String id) throws Exception {
        Resident result = null;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        result = jdbcSession.findById(Resident.class, id);
        //如果是业主获取业主的未绑定和已绑定房屋
        if (Objects.nonNull(result) && Objects.nonNull(result.getType()) && Objects.equal(result.getType().getId(), ResidentType.OWNER.getId())) {
            List<String> residentHouseIds = new ArrayList<>();
            List<String> houseIds = new ArrayList<>();
            List<String> houseNames = new ArrayList<>();
            List<String> bindTypeList = new ArrayList<>();
            bindTypeList.add(BindType.NO_BIND.getId());
            bindTypeList.add(BindType.BIND.getId());
            List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("residentNo", result.getId())
                    .eq("type", ResidentType.OWNER)
                    .in("bindType", bindTypeList)
                    .exe();
            residentHouseList.forEach(v -> {
                String unitName = Objects.isNull(v.getUnitName()) ? "" : v.getUnitName();
                String houseName = v.getCommunityName() + v.getBuildName() + unitName + v.getHouseName();
                residentHouseIds.add(v.getId());
                houseIds.add(v.getHouseNo());
                houseNames.add(houseName);
            });
            result.setResidentHouseIds(residentHouseIds);
            result.setHouseIds(houseIds);
            result.setHouseNames(houseNames);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }

    /**
     * 根据条件获取住户列表
     * userIds
     * tagNames
     *
     * @param jsonObject 查询对象
     * @return 住户列表
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentList")
    @Override
    public Page<Resident> getResidentList(JSONObject jsonObject) throws Exception {
        Page<Resident> result = null;
        if (logger.isDebugEnabled()) {
            //logger.debug("parameter:{}",jsonObject);
        }
        FindPage<Resident> find = jdbcSession.findPage(Resident.class)
                .eq(jsonObject, "id", "classifyId", "cardNo")
                .eq("deleted", false)
                .between("createTime", jsonObject, "beginTime", "endTime")
                .like(jsonObject, "nickname", "realname", "mobile", "address")
                .order("createTime", "desc");

        String search = jsonObject.getString("search");
        if (Objects.nonEmpty(search)) {
            find.markBegin();
            find.like("realname", search).or();
            find.like("nickname", search).or();
            find.like("mobile", search).or();
            find.markEnd();
        }

        //构建多个标志查询
        JSONArray ids = jsonObject.getJSONArray("ids");
        if (Objects.nonEmpty(ids)) {
            find.in("id", ids);
        }
        //可以过滤某个标签的住户信息
        List<String> tagNames = Objects.nonEmpty(jsonObject.getString("tagNames")) ? Arrays.asList(jsonObject.getString("tagNames").split(",")) : null;
        if (Objects.nonEmpty(tagNames)) {
            find.markBegin();
            for (Object tagName : tagNames) {
                find.like("tagNames", tagName).or();
            }
            find.markEnd().and();
        }
        //可以过滤某个员工的住户信息(11,22,33)
        List<String> userIds = getUserId(jsonObject.getString("userIds"));
        if (Objects.nonEmpty(userIds)) {
            find.markBegin();
            for (Object userId : userIds) {
                find.like("users", userId).or();
            }
            find.markEnd().and();
        }

        //查询没有员工跟进的住户(isExistUser=0)
        String emptyUser = jsonObject.getString("isExistUser");
        if (Objects.nonEmpty(emptyUser) && Objects.equal("0", emptyUser)) {
            find.isNull("users");
        }else if (Objects.nonEmpty(emptyUser) && Objects.equal("1", emptyUser)) {
            find.isNotNull("users");
        }
        Integer pageSize = jsonObject.getInteger("pageSize");
        if (pageSize == null) {
            jsonObject.put("pageSize", Short.MAX_VALUE);
        }
        find.page(jsonObject);

        result = find.exe();
        //根据不同员工条件重新设置tag信息,根据数据库tag信息重新解析回去
        List<Resident> residentList = result.getList();
        ResidentTagUtil.renderTags(userIds, residentList);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }


    @ReqMapping("/getResidentListByMobiles")
    public Object getResidentListByMobileList(JSONObject jsonObject) {
        JSONArray mobiles = jsonObject.getJSONArray("mobiles");
        if(Objects.isEmpty(mobiles)){
            return new ArrayList<>();
        }
        List<ResidentHouse> dbResidentList = jdbcSession.findArray(ResidentHouse.class)
                .eq("deleted", false)
                .in("mobile", mobiles)
                .exe();

        if(Objects.isEmpty(dbResidentList)){
            return new ArrayList<>();
        }
        return dbResidentList;
    }


    @ReqMapping("/getResidentListByHouseIds")
    public Object getResidentListByHouseIds(JSONObject jsonObject) {
        JSONArray ids = jsonObject.getJSONArray("ids");
        if(Objects.isEmpty(ids)){
            return new ArrayList<>();
        }

        FindArray<ResidentHouse> find = jdbcSession.findArray(ResidentHouse.class);
        find.eq("deleted",false);
        find.in("houseNo",ids);
        return find.exe();
    }



    /**
     * 如果没有传入分页参数，则设置返回不分页数据
     *
     * @param jsonObject 查询条件
     */
    void buildPage(JSONObject jsonObject) {

    }

    //构建FindPage的in条件
    void buildFindIn(FindPage<Resident> find, JSONObject jsonObject, String key, String dbKey) {
        try {
            JSONArray jsonArray = JSONObject.parseArray(jsonObject.getString(key));
            List<String> list = JSONObject.parseArray(jsonArray.toJSONString(), String.class);
            if (Objects.nonEmpty(list)) {
                find.in(dbKey, list);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 保存住户
     *
     * @param resident 住户对象
     * @return 住户对象
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @ReqMapping("/saveResident")
    @Override
    public Resident
    saveResident(Resident resident) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + resident);
        }
        //新增住户新增或更新账户信息
        String accountNo = saveOrUpdateAccount(resident);

        if (Objects.isEmpty(accountNo)) {
            throw new RuntimeException("新增或更新账户失败.");
        }
        //新增设置住户编号为账户表编号
        resident.setId(accountNo);
        //房屋编号集合
        List<String> houseIds = resident.getHouseIds();

        //商铺编号集合
        List<String> shopIds = resident.getShopIds();

        //车位编号集合
        List<String> parkingIds = resident.getParkingIds();

        String userId = resident.getUserId();
        String userName = resident.getUserName();
        if (Objects.nonEmpty(userId) && Objects.nonEmpty(userName)) {
            //处理跟进人信息
            setUsers(userId, userName, resident);
            //处理标签信息
            ResidentTagUtil.setTag(userId, resident.getTagIds(), resident.getTagNames(), resident);
        }
        //设置首字母
        resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getRealname()));




        //新增住户,如果住户已经存在账户信息,物业不存在住户信息,则进行新增,否者进行更新
        Resident dbResident = getResidentById(resident.getId());
        if (Objects.isNull(dbResident)) {
            jdbcSession.insert(resident);
            //保存或更新用户的业务标签
            saveOrUpdateUserTag(resident);
        } else {
            jdbcSession.updateById(resident);
            //保存或更新用户的业务标签
            saveOrUpdateUserTag(resident);
        }


        //如果存在房屋编号集合则进行房屋绑定操作
        if (Objects.nonEmpty(houseIds)) {
            //新增绑定的房屋如果被占用则进行提示
            for (String houseId : houseIds) {
                List<String> bindTypeList = new ArrayList<>();
                bindTypeList.add(BindType.NO_BIND.getId());
                bindTypeList.add(BindType.BIND.getId());
                List<ResidentHouse> residentHouseList = null;
                if (Objects.equal(resident.getType().getId(), ResidentType.OWNER.getId())) {
                    residentHouseList = residentAssetsService.getResidentHouseList(houseId, resident.getType().getId(), bindTypeList);
                } else {
                    residentHouseList = residentAssetsService.getResidentHouseList(houseId, resident.getType().getId(), bindTypeList, resident.getId());
                }
                if (Objects.nonEmpty(residentHouseList)) {
                    throw new RuntimeException("不允许重复绑定房屋");
                }

            }

            JSONArray houseList = residentAssetsService.getHouseList(houseIds);
            if (Objects.nonEmpty(houseList)) {
                for (Object houseObj : houseList) {
                    JSONObject house = (JSONObject) houseObj;
                    ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(resident, house);
                    //设置房屋业主相关信息
                    residentAssetsService.buildPname(resident, residentHouse);

                    saveResidentHouse(residentHouse);

                    //如果业主绑定房屋会写房屋信息
                    if (Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
                        updateOwnerHouseResult(residentHouse);
                    }

                }
            }
        }


        //如果存在商铺编号集合则进行商铺绑定操作
        if (Objects.nonEmpty(shopIds)) {
            //新增绑定的商铺如果被占用则进行提示
            for (String shopId : shopIds) {
                List<String> bindTypeList = new ArrayList<>();
                bindTypeList.add(BindType.NO_BIND.getId());
                bindTypeList.add(BindType.BIND.getId());
                List<ResidentHouse> residentHouseList = null;
                if (Objects.equal(resident.getType().getId(), ResidentType.OWNER.getId())) {
                    residentHouseList = residentAssetsService.getResidentHouseList(shopId, resident.getType().getId(), bindTypeList);
                } else {
                    residentHouseList = residentAssetsService.getResidentHouseList(shopId, resident.getType().getId(), bindTypeList, resident.getId());
                }
                if (Objects.nonEmpty(residentHouseList)) {
                    throw new RuntimeException("不允许重复绑定商铺");
                }

            }

            JSONArray shopList = residentAssetsService.getShopList(shopIds);
            if (Objects.nonEmpty(shopList)) {
                for (Object shopObj : shopList) {
                    JSONObject shop = (JSONObject) shopObj;
                    ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(resident, shop);
                    residentHouse.setBuildNo(shop.getString("shopClassifyNo"));
                    residentHouse.setBuildName(shop.getString("shopClassifyName"));
                    residentHouse.setHouseType(HouseType.SHOP);
                    //设置房屋业主相关信息
                    residentAssetsService.buildPname(resident, residentHouse);

                    saveResidentHouse(residentHouse);

                    //如果业主绑定房屋会写房屋信息
                    if (Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
                        residentAssetsService.updateOwnerShopResult(residentHouse);
                    }

                }
            }
        }

        //如果存在商铺编号集合则进行商铺绑定操作
        if (Objects.nonEmpty(parkingIds)) {
            //新增绑定的商铺如果被占用则进行提示
            for (String parkingId : parkingIds) {
                List<String> bindTypeList = new ArrayList<>();
                bindTypeList.add(BindType.NO_BIND.getId());
                bindTypeList.add(BindType.BIND.getId());
                List<ResidentHouse> residentHouseList = null;
                if (Objects.equal(resident.getType().getId(), ResidentType.OWNER.getId())) {
                    residentHouseList = residentAssetsService.getResidentHouseList(parkingId, resident.getType().getId(), bindTypeList);
                } else {
                    residentHouseList = residentAssetsService.getResidentHouseList(parkingId, resident.getType().getId(), bindTypeList, resident.getId());
                }
                if (Objects.nonEmpty(residentHouseList)) {
                    throw new RuntimeException("不允许重复绑定车位");
                }

            }

            JSONArray parkingList = residentAssetsService.getParkingList(parkingIds);
            if (Objects.nonEmpty(parkingList)) {
                for (Object parkingObj : parkingList) {
                    JSONObject parking = (JSONObject) parkingObj;
                    ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(resident, parking);
                    residentHouse.setBuildNo(parking.getString("yardNo"));
                    residentHouse.setBuildName(parking.getString("yardName"));
                    residentHouse.setHouseType(HouseType.PARKING);
                    //设置房屋业主相关信息
                    residentAssetsService.buildPname(resident, residentHouse);

                    saveResidentHouse(residentHouse);

                    //如果业主绑定房屋会写房屋信息
                    if (Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
                        residentAssetsService.updateOwnerParkingResult(residentHouse);
                    }

                }
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("result:" + resident);
        }
        return resident;
    }

    /**
     * 报错或更新用户的业务标签
     * @param resident 用户信息
     * @throws Exception
     */
    public void saveOrUpdateUserTag(Resident resident) throws Exception{
        if(Objects.isEmpty(resident.getCreateBy())){
            logger.error("新增用户的业务标签创建人不能为空.");
            return;
        }
        JSONArray addTagDataList = new JSONArray();
        if(Objects.nonNull(resident.getGender())) {
            JSONObject tagObj = new JSONObject();
            tagObj.put("tagGroupName", "性别");
            tagObj.put("tagName", resident.getGender().getDesc());
            addTagDataList.add(tagObj);
        }
        if(Objects.nonEmpty(resident.getOfferName())) {
            JSONObject tagObj = new JSONObject();
            tagObj= new JSONObject();
            tagObj.put("tagGroupName","职业");
            tagObj.put("tagName",resident.getOfferName());
            addTagDataList.add(tagObj);
        }
        if(Objects.nonEmpty(resident.getAddress())) {
            JSONObject tagObj = new JSONObject();
            tagObj= new JSONObject();
            tagObj.put("tagGroupName","地区");
            tagObj.put("tagName",resident.getAddress());
            addTagDataList.add(tagObj);
        }
        if(Objects.nonNull(resident.getBirthDay())) {
            JSONObject tagObj = new JSONObject();
            tagObj= new JSONObject();
            tagObj.put("tagGroupName","年龄");
            String age=String.valueOf(resident.getBirthDay().getYear());
            int val=Integer.parseInt(age.substring(age.length()-2,age.length()));
            if(val>=40 && val<49){
                tagObj.put("tagName","40后");
            }else if(val>=50 && val<59){
                tagObj.put("tagName","50后");
            }else if(val>=60 && val<69){
                tagObj.put("tagName","60后");
            }else if(val>=70 && val<79){
                tagObj.put("tagName","70后");
            }else if(val>=80 && val<89){
                tagObj.put("tagName","80后");
            }else if(val>=90 && val<99){
                tagObj.put("tagName","90后");
            }else if(val>=0 && val<9){
                tagObj.put("tagName","00后");
            }else if(val>=10 && val<19){
                tagObj.put("tagName","10后");
            }else if(val>=20 && val<29){
                tagObj.put("tagName","20后");
            }else if(val>=30 && val<39){
                tagObj.put("tagName","30后");
            }
            addTagDataList.add(tagObj);
        }

        if (Objects.nonEmpty(addTagDataList)) {
            JSONObject businessTagResult=doveClient.post("/admin/business/tag/service/batch/add", (http) -> {
                JSONObject body = new JSONObject();
                body.put("dataList", addTagDataList);
                http.setBody(body.toJSONString());
            });
            if (businessTagResult.getIntValue("code") == 200) {
                JSONArray businessTagList = businessTagResult.getJSONArray("data");
                if(Objects.nonEmpty(businessTagList)){
                    doveClient.post("/crm/user/tag/service/batch/add", (http) -> {
                        JSONObject body = new JSONObject();
                        body.put("type","3");//业务标签
                        body.put("userNo",resident.getId());
                        if(Objects.nonEmpty(resident.getRealname())){
                            body.put("userName", resident.getRealname());
                        }else{
                            body.put("userName", resident.getNickname());
                        }
                        body.put("communityNo","");
                        body.put("communityName","");
                        body.put("createBy",resident.getCreateBy());
                        body.put("createName",resident.getCreateName());
                        body.put("userTagList", businessTagList);
                        http.setBody(body.toJSONString());
                    });
                }
            }

        }
    }

    /**
     * 新增或更新账户信息
     * 1.住户编号与账户编号一致
     *
     * @param resident 住户信息
     * @throws Exception
     */
    private String saveOrUpdateAccount(Resident resident) throws Exception {
        String accountNo = "";
        JSONObject saveOrUpdateAccountResult = doveClient.post("/auth/account/service/saveOrUpdateAccount", (http) -> {
            JSONObject body = new JSONObject();
            body.put("id", resident.getId());
            //body.put("account", resident.getMobile());
            body.put("realname", resident.getRealname());
            body.put("avatar", resident.getAvatar());
            body.put("mobile", resident.getMobile());
            //body.put("idCard", resident.getCardNo());
            List<String> khtIds = new ArrayList<>();
            khtIds.add(resident.getCompanyNo());
            body.put("khtIds", khtIds);
            http.setBody(body.toJSONString());
        });
        if (saveOrUpdateAccountResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.saveOrUpdateAccountResult 新增或更新住户对应的账户信息.后续修复数据一致性");
        }
        JSONObject accountJsonObject = saveOrUpdateAccountResult.getJSONObject("data");
        if (Objects.nonEmpty(accountJsonObject)) {
            accountNo = accountJsonObject.getString("id");
        }
        return accountNo;
    }

    /**
     * 更新住户
     *
     * @param resident 住户对象
     * @return 更新条数
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    @ReqMapping("/updateResident")
    @Override
    public Resident updateResident(Resident resident) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + resident);
        }


        //新增或更新账户信息
        saveOrUpdateAccount(resident);



        //房屋编号集合
        List<String> houseIds = resident.getHouseIds();

        //商铺编号集合
        List<String> shopIds = resident.getShopIds();

        //车位编号集合
        List<String> parkingIds = resident.getParkingIds();

        String userId = resident.getUserId();
        String userName = resident.getUserName();
        if (Objects.nonEmpty(userId) && Objects.nonEmpty(userName)) {
            //处理跟进人信息
            setUsers(userId, userName, resident);
            //处理标签信息
            ResidentTagUtil.setTag(userId, resident.getTagIds(), resident.getTagNames(), resident);
        }

        //是否更新冗余的租户数据
        boolean isUpdateData = false;
        Resident oldResident = getResidentById(resident.getId());
        if (!Objects.equal(oldResident.getRealname(), resident.getRealname()) || !Objects.equal(oldResident.getMobile(), resident.getMobile())) {
            isUpdateData = true;
        }

        //设置首字母
        resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getRealname()));
        jdbcSession.updateById(resident);
        //保存或更新用户的业务标签
        saveOrUpdateUserTag(resident);

        if (isUpdateData) {
            //级联批量修改房屋已绑定业主是当前住户的资料
            batchUpdateHouseOwner(resident);

            //级联批量修改商铺已绑定业主是当前住户的资料
            batchUpdateShopOwner(resident);

            //级联批量修改车位已绑定业主是当前住户的资料
            batchUpdateParkingOwner(resident);

            //级联批量修改住户房屋的住户资料
            batchUpdateResidentHouse(resident);
        }
        if (Objects.nonEmpty(houseIds)) {
            residentAssetsService.updateResidentAssets(resident, houseIds, HouseType.HOUSE.getId());
        }

        if (Objects.nonEmpty(shopIds)) {
            residentAssetsService.updateResidentAssets(resident, shopIds, HouseType.SHOP.getId());
        }

        if (Objects.nonEmpty(parkingIds)) {
            residentAssetsService.updateResidentAssets(resident, parkingIds, HouseType.PARKING.getId());
        }

        if (logger.isDebugEnabled()) {
            logger.debug("result:" + resident);
        }
        return resident;
    }

    /**
     * 更新房屋业主信息接口
     *
     * @param residentHouse 住户房屋信息
     * @throws Exception 异常
     */
    private void updateOwnerHouseResult(ResidentHouse residentHouse) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/house/service/update", (http) -> {
            http.addHeader("companyNo", residentHouse.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("id", residentHouse.getHouseNo());
            body.put("ownerNo", residentHouse.getResidentNo());
            body.put("ownerName", residentHouse.getRealname());
            body.put("ownerMobile", residentHouse.getMobile());

            Subject subject = SubjectUtil.getSubject();
            UserLoginInfo userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
            if (userLoginInfo != null) {
                body.put("operateName", userLoginInfo.getUsername());
                body.put("operateNo", userLoginInfo.getUserId());
            }
            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.updateOwnerHouseResult 回写房屋住户信息失败.后续修复数据一致性");
        }
    }

    /**
     * 更新商铺业主信息接口
     *
     * @param residentHouse 住户房屋信息
     * @throws Exception 异常
     */
    private void updateOwnerShopResult(ResidentHouse residentHouse) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/shop/service/update", (http) -> {
            http.addHeader("companyNo", residentHouse.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("id", residentHouse.getHouseNo());
            body.put("ownerNo", residentHouse.getResidentNo());
            body.put("ownerName", residentHouse.getRealname());
            body.put("ownerMobile", residentHouse.getMobile());

            Subject subject = SubjectUtil.getSubject();
            UserLoginInfo userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
            body.put("operateName", userLoginInfo.getUsername());
            body.put("operateNo", userLoginInfo.getUserId());

            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.updateOwnerShopResult 回写房屋住户信息失败.后续修复数据一致性");
        }
    }

    /**
     * 更新车位业主信息接口
     *
     * @param residentHouse 住户房屋信息
     * @throws Exception 异常
     */
    private void updateOwnerParkingResult(ResidentHouse residentHouse) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/parking/service/update", (http) -> {
            http.addHeader("companyNo", residentHouse.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("id", residentHouse.getHouseNo());
            body.put("ownerNo", residentHouse.getResidentNo());
            body.put("ownerName", residentHouse.getRealname());
            body.put("ownerMobile", residentHouse.getMobile());

            Subject subject = SubjectUtil.getSubject();
            UserLoginInfo userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
            body.put("operateName", userLoginInfo.getUsername());
            body.put("operateNo", userLoginInfo.getUserId());

            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.updateOwnerParkingResult 回写房屋住户信息失败.后续修复数据一致性");
        }
    }


    /**
     * 校验住户对象的类型是否是业主
     *
     * @param resident 住户信息
     * @return true 是业主 false 不是业主
     */
    protected boolean isOwner(Resident resident) {
        if (Objects.isNull(resident) || Objects.isEmpty(resident.getId()) || Objects.isNull(resident.getType())) {
            return false;
        }
        return Objects.equal(resident.getType().getId(), ResidentType.OWNER.getId());
    }

    /**
     * 批量更新房屋业主信息
     *
     * @param resident 业主信息
     * @throws Exception 异常
     */
    private void batchUpdateHouseOwner(Resident resident) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/house/service/batchUpdateHouseOwner", (http) -> {
            http.addHeader("companyNo", resident.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("ownerNo", resident.getId());
            body.put("ownerName", resident.getRealname());
            body.put("ownerMobile", resident.getMobile());
            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.batchUpdateHouseOwner 批量更新房屋业主信息失败.后续修复数据一致性");
        }
    }

    /**
     * 批量更新店铺业主信息
     *
     * @param resident 业主信息
     * @throws Exception 异常
     */
    private void batchUpdateShopOwner(Resident resident) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/shop/service/batchUpdateShopOwner", (http) -> {
            http.addHeader("companyNo", resident.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("ownerNo", resident.getId());
            body.put("ownerName", resident.getRealname());
            body.put("ownerMobile", resident.getMobile());
            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.batchUpdateHouseOwner 批量更新店铺业主信息失败.后续修复数据一致性");
        }
    }

    /**
     * 批量更新店铺业主信息
     *
     * @param resident 业主信息
     * @throws Exception 异常
     */
    private void batchUpdateParkingOwner(Resident resident) throws Exception {
        JSONObject updateHouseResult = doveClient.post("/basic/parking/service/batchUpdateParkingOwner", (http) -> {
            http.addHeader("companyNo", resident.getCompanyNo());
            JSONObject body = new JSONObject();
            body.put("ownerNo", resident.getId());
            body.put("ownerName", resident.getRealname());
            body.put("ownerMobile", resident.getMobile());
            http.setBody(body.toJSONString());
        });
        if (updateHouseResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.batchUpdateParkingOwner 批量更新车位业主信息失败.后续修复数据一致性");
        }
    }


    /***
     * 根据住户标志删除住户信息
     * @param id 住户标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentById")
    @Override
    public Boolean deleteResidentById(String id) throws Exception {
        boolean flag = false;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        if (!Objects.isEmpty(id)) {
            Resident result = Pool.get(Resident.class, id);
            if (result != null) {
                result.setDeleted(true);
                jdbcSession.updateById(result);

                //级联删除业务汽车信息
                final List<ResidentCar> residentCarList = jdbcSession.findArray(ResidentCar.class)
                        .eq("residentNo", result.getId())
                        .exe();
                for (ResidentCar residentCar : residentCarList) {
                    deleteResidentCarById(residentCar.getId());
                }

                //级联删除业务家庭信息
                final List<ResidentFamily> residentFamilyList = jdbcSession.findArray(ResidentFamily.class)
                        .eq("residentNo", result.getId())
                        .exe();
                for (ResidentFamily residentFamily : residentFamilyList) {
                    deleteResidentFamilyById(residentFamily.getId());
                }

                //级联删除业务房产信息
                final List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("residentNo", result.getId())
                        .exe();
                for (ResidentHouse residentHouse : residentHouseList) {
                    deleteResidentHouseById(residentHouse.getId());
                }


                flag = true;
            }
        }
        return flag;
    }


    /**
     * 批量保存或更新住户信息
     *
     * @param condition 住户信息数据
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/batchSaveOrUpdateResident")
    @Override
    public Boolean batchSaveOrUpdateResident(JSONObject condition) throws Exception {
        boolean flag = false;
        List<Resident> insertResidentList = new ArrayList<>();
        List<Resident> updateResidentList = new ArrayList<>();
        JSONArray residentList = condition.getJSONArray("residentList");
        Token token = (Token) condition.get("token");
        if (Objects.nonEmpty(residentList)) {
            //构建其他接口的参数信息(ids,tagIds,employeeIds)
            Map<String, List<String>> context = buildBaseContext(residentList);
            //获取住户ID集合
            List<String> idsSet = context.get("ids");

            //获取住户标签ID集合
            List<String> tagIdsSet = context.get("tagIds");

            //获取员工ID集合
            List<String> employeeIdsSet = context.get("employeeIds");

            //获取存在的住户ID与住户对象映射(性能优化)
            Map<String, Resident> residentMapping = batchGetResidentMapping(idsSet);

            logger.info("residentMapping:{}",residentMapping);

            //所有标签ID与名称映射
            Map<String, String> tagMapping = batchGetTagMapping(token.getCompanyNo(), tagIdsSet);

            //所有员工ID与名称映射
            Map<String, String> employeeMapping = batchGetEmployeeMapping(token.getCompanyNo(), employeeIdsSet);

            if (Objects.isEmpty(employeeMapping)) {
                logger.error("员工ID与名称映射错误.");
                return false;
            }

            for (int i = 0; i < residentList.size(); i++) {
                JSONObject jsonObject = residentList.getJSONObject(i);

                String id = jsonObject.getString("id");
                String userId = jsonObject.getString("userId");
                String userName = employeeMapping.get(userId);
                //Resident resident = jdbcSession.findById(Resident.class, id);

                logger.info("住户id:{}",id);
                Resident resident = residentMapping.get(id);
                logger.info("住户id:{},内容：{}",id,resident);
                //通过查询数据库是否有记录判断是新增还是更新
                if (Objects.isNull(resident)) {
                    resident = Pool.newInstance(Resident.class, id);
                    resident.setAvatar(jsonObject.getString("avatar"));
                    resident.setNickname(jsonObject.getString("nickname"));
                    resident.setRealname(resident.getNickname());
                    //设置首字母
                    resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getRealname()));
                    resident.setCorpName(jsonObject.getString("corpName"));
                    //默认为住户,同步没有这个字段前段报错
                    resident.setType(ResidentType.OWNER);
                    String genderJsonStr = jsonObject.getString("gender");
                    JSONObject genderJson = JSONObject.parseObject(genderJsonStr);
                    String genderId = genderJson.getString("id");
                    Gender gender = Enums.getEnum(Gender.class, genderId);
                    resident.setMobile(jsonObject.getString("mobile"));
                    resident.setGender(gender);
                    if (Objects.nonEmpty(userId)) {
                        //处理跟进人信息
                        setUsers(userId, userName, resident);

                        //处理住户标签信息,把标签编号转标签名称
                        JSONArray tagIdsJsonArray = jsonObject.getJSONArray("tagIds");
//                        JSONArray tagNamesJsonArray = jsonObject.getJSONArray("tagNames");
                        if (Objects.nonEmpty(tagIdsJsonArray)) {
                            List<String> tagIds = JSONObject.parseArray(tagIdsJsonArray.toJSONString(), String.class);
                            if (Objects.nonEmpty(tagIds)) {
                                List<String> tagNames = new ArrayList<>();
                                for (String tagId : tagIds) {
                                    tagNames.add(tagMapping.get(tagId));
                                }
                                ResidentTagUtil.setTag(userId, tagIds, tagNames, resident);
                            }

                            //增加用户的第三方标签
                            Resident finalResident = resident;
                            doveClient.post("/crm/user/tag/service/third/batch/add", (http) -> {
                                JSONObject body = new JSONObject();
                                body.put("type","4");//第三方标签
                                body.put("userNo", finalResident.getId());
                                if(Objects.nonEmpty(finalResident.getRealname())){
                                    body.put("userName", finalResident.getRealname());
                                }else{
                                    body.put("userName", finalResident.getNickname());
                                }
                                body.put("communityNo","");
                                body.put("communityName","");
                                body.put("createBy",userId);
                                body.put("createName",userName);
                                body.put("tagIds", tagIds);
                                http.setBody(body.toJSONString());
                            });
                        }
                    }
                    //residentMapping.put(id,resident);


                    insertResidentList.add(resident);
                } else {
                    resident.setAvatar(jsonObject.getString("avatar"));
                    resident.setNickname(jsonObject.getString("nickname"));
                    //设置首字母
                    resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getNickname()));
                    resident.setCorpName(jsonObject.getString("corpName"));
                    String genderJsonStr = jsonObject.getString("gender");
                    JSONObject genderJson = JSONObject.parseObject(genderJsonStr);
                    String genderId = genderJson.getString("id");
                    Gender gender = Enums.getEnum(Gender.class, genderId);
                    resident.setGender(gender);
                    //手机号不为空则更新住户手机
                    String mobile = jsonObject.getString("mobile");
                    if (Objects.nonEmpty(mobile)) {
                        resident.setMobile(jsonObject.getString("mobile"));
                    }
                    if (Objects.nonEmpty(userId)) {
                        //处理跟进人信息
                        setUsers(userId, userName, resident);
                        //处理住户标签信息
                        JSONArray tagIdsJsonArray = jsonObject.getJSONArray("tagIds");
//                        JSONArray tagNamesJsonArray = jsonObject.getJSONArray("tagNames");
                        if (Objects.nonEmpty(tagIdsJsonArray)) {
                            List<String> tagIds = JSONObject.parseArray(tagIdsJsonArray.toJSONString(), String.class);
                            if (Objects.nonEmpty(tagIds)) {
                                List<String> tagNames = new ArrayList<>();
                                for (String tagId : tagIds) {
                                    tagNames.add(tagMapping.get(tagId));
                                }
                                ResidentTagUtil.setTag(userId, tagIds, tagNames, resident);
                                //增加用户的第三方标签
                                Resident finalResident = resident;
                                doveClient.post("/crm/user/tag/service/third/batch/add", (http) -> {
                                    JSONObject body = new JSONObject();
                                    body.put("type","4");//第三方标签
                                    body.put("userNo", finalResident.getId());
                                    if(Objects.nonEmpty(finalResident.getRealname())){
                                        body.put("userName", finalResident.getRealname());
                                    }else{
                                        body.put("userName", finalResident.getNickname());
                                    }
                                    body.put("communityNo","");
                                    body.put("communityName","");
                                    body.put("createBy",userId);
                                    body.put("createName",userName);
                                    body.put("tagIds", tagIds);
                                    http.setBody(body.toJSONString());
                                });
                            }
                        }
                    }
                    updateResidentList.add(resident);
                }
            }
            if (Objects.nonEmpty(insertResidentList)) {
                jdbcSession.insert(insertResidentList);
            }
            if (Objects.nonEmpty(updateResidentList)) {
                jdbcSession.updateById(updateResidentList);
            }
            flag = true;
        }
        return flag;
    }

    /**
     * 根据条件查询住户ID与住户对象映射map
     *
     * @param ids 住户ID集合
     * @return 住户ID与住户对象映射Map
     */
    private Map<String, Resident> batchGetResidentMapping(List<String> ids) {
        //住户ID与住户对象映射
        Map<String, Resident> mapping = new HashMap<>();
        //根据住户ID集合查询符合条件的住户信息集合
        final List<Resident> residentList = jdbcSession.findArray(Resident.class)
                .in("id", ids)
                .exe();
        if(Objects.nonEmpty(residentList)){
            //把住户信息转换成住户ID与住户对象映射map返回出来
            mapping = residentList.stream().collect(Collectors.toMap(Resident::getId, resident -> resident));
        }
        return mapping;
    }

    @ReqMapping("/batch/ids")
    public Object batchGetResidentByIds(JSONObject jsonObject) {
        JSONArray ids = jsonObject.getJSONArray("ids");
        if(Objects.isEmpty(ids)){
            return new ArrayList<>();
        }
        List<Resident> residentList = jdbcSession.findArray(Resident.class)
                .in("id", ids)
                .exe();
        return residentList;
    }



    /**
     * 通过一次遍历统一构建请求外部或内容接口的参数
     *
     * @param residentArray 住户信息数组
     * @return 住户ID与住户对象映射Map
     */
    private Map<String, List<String>> buildBaseContext(JSONArray residentArray) throws Exception {
        Map<String, List<String>> context = new HashMap<>();
        //获取住户ID集合
        Set<String> ids = new HashSet<>();

        //获取住户标签ID集合
        Set<String> tagIds = new HashSet<>();

        //获取员工ID集合
        Set<String> employeeIds = new HashSet<>();

        residentArray.forEach(val -> {
            //追加住户ID
            JSONObject jsonObject = (JSONObject) val;
            ids.add(jsonObject.getString("id"));
            //追加标签ID
            JSONArray tagIdsJsonArray = jsonObject.getJSONArray("tagIds");
            if (Objects.nonEmpty(tagIdsJsonArray)) {
                List<String> tagIdsList = JSONObject.parseArray(tagIdsJsonArray.toJSONString(), String.class);
                tagIds.addAll(tagIdsList);
            }
            //追加员工ID
            employeeIds.add(jsonObject.getString("userId"));
        });
        context.put("ids", new ArrayList<>(ids));
        context.put("tagIds", new ArrayList<>(tagIds));
        context.put("employeeIds", new ArrayList<>(employeeIds));
        return context;
    }

    /**
     * 根据条件查询标签ID与标签名称映射
     *
     * @param ids 标签ID集合
     * @return 标签ID与标签名称映射Map
     */
    private Map<String, String> batchGetTagMapping(String companyNo, List<String> ids) throws Exception {
        //住户ID与住户对象映射
        Map<String, String> mapping = new HashMap<>();
        JSONObject tagResult = doveClient.post("/crm/tag/getTagList", (http) -> {
            http.addHeader("companyNo", companyNo);
            JSONObject body = new JSONObject();
            body.put("ids", ids);
            body.put("group", false);
            body.put("pageSize", Short.MAX_VALUE);
            http.setBody(body.toJSONString());
        });
        JSONArray tagList = tagResult.getJSONObject("data").getJSONArray("list");
        if (Objects.nonEmpty(tagList)) {
            for (Object tagObj : tagList) {
                JSONObject tag = (JSONObject) tagObj;
                mapping.put(tag.getString("id"), tag.getString("name"));
            }
        }
        return mapping;
    }

    /**
     * 根据条件查询员工ID与员工名称映射
     *
     * @param ids 员工ID集合
     * @return 住户ID与住户对象映射Map
     */
    private Map<String, String> batchGetEmployeeMapping(String companyNo, List<String> ids) throws Exception {
        //住户ID与住户对象映射
        Map<String, String> mapping = new HashMap<>();
        JSONObject employeeResult = doveClient.post("/basic/employee/service/list", (http) -> {
            http.addHeader("companyNo", companyNo);
            JSONObject body = new JSONObject();
            body.put("id", ids);
            body.put("pageSize", Short.MAX_VALUE);
            http.setBody(body.toJSONString());
        });
        //所有员工ID与名称映射
        JSONArray employeeList = employeeResult.getJSONObject("data").getJSONArray("list");
        if (Objects.nonEmpty(employeeList)) {
            for (Object employeeObj : employeeList) {
                JSONObject employee = (JSONObject) employeeObj;
                mapping.put(employee.getString("id"), employee.getString("name"));
            }
        }
        return mapping;
    }

    /**
     * 删除住户相关的跟进人信息
     *
     * @param id     住户标志
     * @param userId 用户编号
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentUser")
    @Override
    public Boolean deleteResidentUser(Token token, String id, String userId) throws Exception {
        boolean flag = false;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }


        if (Objects.nonEmpty(id) && Objects.nonEmpty(userId)) {
            Resident result = Pool.get(Resident.class, id);
            if (result != null) {
                //获取员工ID对应的名字
                List<String> employeeIdsSet = new ArrayList<>();
                employeeIdsSet.add(userId);
                Map<String, String> employeeMapping = batchGetEmployeeMapping(token.getCompanyNo(), employeeIdsSet);
                String userName = employeeMapping.get(userId);


                //跟进用户删除标签
                ResidentTagUtil.removeTags(userId, result);
                //删除跟进人
                result.getUsers().removeIf(userId::equals);
                result.getUserNames().removeIf(userName::equals);
                jdbcSession.updateById(result);
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 根据条件获取住户汽车列表
     *
     * @param jsonObject 查询对象
     * @return 住户汽车列表
     * @throws IOException 操作异常
     */
    @ReqMapping("/getResidentCarList")
    @Override
    public Page<ResidentCar> getResidentCarList(JSONObject jsonObject) throws Exception {
        Page<ResidentCar> result = null;
        if (logger.isDebugEnabled()) {
            //logger.debug("parameter:" + jsonObject.toJSONString());
        }
        result = jdbcSession.findPage(ResidentCar.class)
                .eq(jsonObject, "id", "residentNo", "carNo", "stationNo")
                .eq("deleted", 0)
                .like(jsonObject, "carBrand", "carModel", "carClor")
                .order("createTime", "desc")
                .page(jsonObject).exe();
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }


    /***
     * 根据住户汽车标志获取住户汽车信息
     * @param id 住户汽车标志
     * @return 住户汽车对象
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentCarById")
    @Override
    public ResidentCar getResidentCarById(String id) throws Exception {
        ResidentCar result = null;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        result = jdbcSession.findById(ResidentCar.class, id);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }


    /**
     * 保存住户汽车
     *
     * @param residentCar 住户汽车对象
     * @return 住户汽车对象
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @ReqMapping("/saveResidentCar")
    @Override
    public ResidentCar saveResidentCar(ResidentCar residentCar) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentCar);
        }
        jdbcSession.insert(residentCar);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentCar);
        }
        return residentCar;
    }


    /**
     * 更新住户汽车
     *
     * @param residentCar 住户汽车对象
     * @return 住户汽车对象
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    @ReqMapping("/updateResidentCar")
    @Override
    public ResidentCar updateResidentCar(ResidentCar residentCar) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentCar);
        }
        jdbcSession.updateById(residentCar);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentCar);
        }
        return residentCar;
    }


    /***
     * 根据住户汽车标志删除住户汽车信息
     * @param id 住户汽车标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentCarById")
    @Override
    public Boolean deleteResidentCarById(String id) throws Exception {
        boolean flag = false;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        if (!Objects.isEmpty(id)) {
            ResidentCar result = Pool.get(ResidentCar.class, id);
            if (result != null) {
                result.setDeleted(true);
                jdbcSession.updateById(result);
                flag = true;
            }
        }
        return flag;
    }


    /**
     * 根据条件获取住户家庭成员列表
     *
     * @param jsonObject 查询对象
     * @return 住户家庭成员列表
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentFamilyList")
    @Override
    public Page<ResidentFamily> getResidentFamilyList(JSONObject jsonObject) throws Exception {
        Page<ResidentFamily> result = null;
        if (logger.isDebugEnabled()) {
            //logger.debug("parameter:" + jsonObject.toJSONString());
        }
        result = jdbcSession.findPage(ResidentFamily.class)
                .eq(jsonObject, "residentNo", "name", "mobile", "cardNo")
                .eq("deleted", false)
                .order("createTime", "desc")
                .page(jsonObject).exe();
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }


    /***
     * 根据住户家庭成员标志获取住户家庭成员信息
     * @param id 住户家庭成员标志
     * @return 住户家庭成员对象
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentFamilyById")
    @Override
    public ResidentFamily getResidentFamilyById(String id) throws Exception {
        ResidentFamily result = null;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        result = jdbcSession.findById(ResidentFamily.class, id);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }

    /**
     * 保存住户家庭成员
     *
     * @param residentFamily 住户家庭成员对象
     * @return 新增条数
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @ReqMapping("/saveResidentFamily")
    @Override
    public ResidentFamily saveResidentFamily(ResidentFamily residentFamily) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentFamily);
        }
        jdbcSession.insert(residentFamily);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentFamily);
        }
        return residentFamily;
    }


    /**
     * 更新住户家庭成员
     *
     * @param residentFamily 住户家庭成员对象
     * @return 更新条数
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    @ReqMapping("/updateResidentFamily")
    @Override
    public ResidentFamily updateResidentFamily(ResidentFamily residentFamily) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentFamily);
        }
        jdbcSession.updateById(residentFamily);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentFamily);
        }
        return residentFamily;
    }


    /***
     * 根据住户家庭成员标志删除住户家庭成员信息
     * @param id 住户家庭成员标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentFamilyById")
    @Override
    public Boolean deleteResidentFamilyById(String id) throws Exception {
        boolean flag = false;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        if (!Objects.isEmpty(id)) {
            ResidentFamily result = Pool.get(ResidentFamily.class, id);
            if (result != null) {
                result.setDeleted(true);
                jdbcSession.updateById(result);
                flag = true;
            }
        }
        return flag;
    }


    /**
     * 根据条件获取住户房屋列表
     *
     * @param jsonObject 查询对象
     * @return 住户房屋列表
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentHouseList")
    @Override
    public Page<ResidentHouse> getResidentHouseList(JSONObject jsonObject) throws Exception {
        Page<ResidentHouse> result = null;
        String dataPvType = jsonObject.getString("dataPvType");
        if (logger.isDebugEnabled()) {
            //logger.debug("parameter:" + jsonObject.toJSONString());
        }
        FindPage<ResidentHouse> find = jdbcSession.findPage(ResidentHouse.class)
                .eq(jsonObject, "id", "residentNo", "houseNo", "type", "houseType")
                .in(jsonObject, "bindType")
                .like(jsonObject, "realname", "mobile", "communityName", "houseName","communityNo")
                .order("createTime", "desc");

        //多小区数据权限过滤
        JSONArray communityNos=jsonObject.getJSONArray("communityNos");
        if(Objects.nonEmpty(communityNos)){
            find.in("communityNo",communityNos);
        }
        //中恶鬼
        String deleted=jsonObject.getString("deleted");
        if(Objects.isEmpty(deleted)){
            find.eq("deleted", false);
        }else{
            find.eq("deleted", true);
        }
        //如果传入权限类型则增加数据权限(权限依赖房屋的权限)
        if (Objects.nonEmpty(dataPvType)) {
            List<String> assetsIdList= (List<String>) jsonObject.get("assetsIds");
            find.in("houseNo",assetsIdList);
            logger.info("增加数据权限,权限类型：{},有权限的资产编号：{}",dataPvType,assetsIdList);
        }
        //排除家属管理中选着房屋绑定的业主列表中已成为业主家属的数据(家属组件有用到)
        String excludeFriendNo = jsonObject.getString("excludeFriendNo");
        if (Objects.nonEmpty(excludeFriendNo)) {
            //已经成为业主家属的数据
            List<String> bindTypeList = new ArrayList<>();
            bindTypeList.add(BindType.NO_BIND.getId());
            bindTypeList.add(BindType.BIND.getId());
            List<ResidentHouse> friendHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("type", ResidentType.FRIEND)
                    .eq("residentNo", excludeFriendNo)
                    .in("bindType", bindTypeList)
                    .eq("deleted", false)
                    .exe();
            if (Objects.nonEmpty(friendHouseList)) {
                List<String> houseNoList = friendHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toList());
                find.noIn("houseNo", houseNoList);
            }
        }


        //构建业主绑定过的房屋
        String ownerId = jsonObject.getString("ownerId");
        if (Objects.nonEmpty(ownerId)) {
            List<ResidentHouse> ownerHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("type", ResidentType.OWNER)
                    .eq("residentNo", ownerId)
                    .exe();
            if (Objects.nonEmpty(ownerHouseList)) {
                List<String> houseNoList = ownerHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toList());
                find.in("houseNo", houseNoList);
            } else {
                //防止没有房屋数据查询类型下的所有数据
                find.eq("type", ResidentType.OWNER);
                find.eq("residentNo", ownerId);
            }
        }

        //构建家属所有的房屋
        String friendId = jsonObject.getString("friendId");
        if (Objects.nonEmpty(friendId)) {
            List<ResidentHouse> friendHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("type", ResidentType.FRIEND)
                    .eq("residentNo", friendId)
                    .exe();
            if (Objects.nonEmpty(friendHouseList)) {
                List<String> houseNoList = friendHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toList());
                find.in("houseNo", houseNoList);
            } else {
                //防止没有房屋数据查询类型下的所有数据
                find.eq("residentNo", friendId);
            }
        }

        //查询租户未绑定和已绑定的的房屋
        String lesseeId = jsonObject.getString("lesseeId");
        if (Objects.nonEmpty(lesseeId)) {
            List<ResidentHouse> lesseeHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("type", ResidentType.LESSEE)
                    .eq("residentNo", lesseeId)
                    .exe();
            if (Objects.nonEmpty(lesseeHouseList)) {
                List<String> houseNoList = lesseeHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toList());
                find.in("houseNo", houseNoList);
            } else {
                //防止没有房屋数据查询类型下的所有数据
                find.eq("residentNo", lesseeId);
            }
        }


        //增加模糊搜索
        String search = jsonObject.getString("search");
        if(Objects.nonEmpty(search)){
            find.markBegin();
            find.like("realname", search).or();
            find.like("mobile", search).or();
            find.markEnd();
        }
        result = find.page(jsonObject).exe();
        //构建数据集合业主身份下面的已认证住户数量
        if (Objects.nonNull(result)) {
            List<ResidentHouse> residentHouseList = result.getList();
            for (ResidentHouse residentHouse : residentHouseList) {
                //设置房屋性别字段,后期性别考虑冗余 TODO
                Resident resident = getResidentById(residentHouse.getResidentNo());
                residentHouse.setRealname(resident.getRealname());
                residentHouse.setMobile(resident.getMobile());
                residentHouse.setGender(resident.getGender());
                residentHouse.setCardNo(resident.getCardNo());
                residentHouse.setBirthDay(resident.getBirthDay());


                ResidentType type = residentHouse.getType();
                if (Objects.equal(type.getId(), ResidentType.OWNER.getId())) {
                    List<String> bindTypeList = new ArrayList<>();
                    bindTypeList.add(BindType.BIND.getId());
                    List<ResidentHouse> list = jdbcSession.findArray(ResidentHouse.class)
                            .eq("houseNo", residentHouse.getHouseNo())
                            .in("bindType", bindTypeList)
                            .eq("deleted", false)
                            .exe();
                    residentHouse.setCount(list.size());
                } else {
                    residentHouse.setCount(0);
                }
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }


    /***
     * 根据住户房屋标志获取住户房屋信息
     * @param id 住户房屋标志
     * @return 住户房屋对象
     * @throws Exception 操作异常
     */
    @ReqMapping("/getResidentHouseById")
    @Override
    public ResidentHouse getResidentHouseById(String id) throws Exception {
        ResidentHouse result = null;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        result = jdbcSession.findById(ResidentHouse.class, id);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }

    /**
     * 根据条件获取一条住户房屋信息
     *
     * @param houseNo 房屋编号
     * @return 住户房屋信息
     * @throws Exception 异常
     */
    @ReqMapping("/getOwnerHouse")
    @Override
    public ResidentHouse getOwnerHouse(String houseNo) throws Exception {
        ResidentHouse result = null;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + houseNo);
        }
        result = jdbcSession.findOne(ResidentHouse.class)
                .eq("houseNo", houseNo)
                .eq("type", ResidentType.OWNER)
                .exe();
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + result);
        }
        return result;
    }

    /**
     * 校验住户房屋绑定唯一性
     * 一个房子只能有一个有效(待绑定,已绑定)业主记录
     * 一个房子只能只能有一条有效(待绑定,已绑定)租客或家属记录
     */
    private void checkResidentHouseUnique(ResidentHouse residentHouse) {
        if (Objects.isEmpty(residentHouse.getHouseNo())) {
            throw new RuntimeException("房屋编号不能为空.");
        }
        if (Objects.isEmpty(residentHouse.getResidentNo())) {
            throw new RuntimeException("住户编号不能为空.");
        }
        if (Objects.isNull(residentHouse.getType())) {
            throw new RuntimeException("住户类型不能为空.");
        }

        List<String> bindTypeList = new ArrayList<>();
        bindTypeList.add(BindType.NO_BIND.getId());
        bindTypeList.add(BindType.BIND.getId());
        FindArray<ResidentHouse> find = jdbcSession.findArray(ResidentHouse.class)
                .eq("houseNo", residentHouse.getHouseNo())
                .in("bindType", bindTypeList)
                .eq("deleted", false);
        if (Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
            find.eq("type", ResidentType.OWNER);
            find.eq("deleted", false);
            List<ResidentHouse> residentHouseList = find.exe();
            if (Objects.nonEmpty(residentHouseList)) {
                ResidentHouse ownerHouse = residentHouseList.get(0);
                if (Objects.equal(residentHouse.getResidentNo(), ownerHouse.getResidentNo())) {
                    throw new RuntimeException("不允许重复新增");
                } else {
                    throw new RuntimeException("当前房屋已经被其业主锁定");
                }
            }
        } else {
            find.eq("type", residentHouse.getType());
            find.eq("residentNo", residentHouse.getId());
            find.eq("deleted", false);
            List<ResidentHouse> residentHouseList = find.exe();
            if (Objects.nonEmpty(residentHouseList)) {
                throw new RuntimeException("不允许重复新增");
            }
        }
    }

    /**
     * 保存住户房屋
     *
     * @param residentHouse 住户房屋对象
     * @return 新增条数
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @ReqMapping("/saveResidentHouse")
    @Override
    public ResidentHouse saveResidentHouse(ResidentHouse residentHouse) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentHouse);
        }
        //重复数据唯一校验
        checkResidentHouseUnique(residentHouse);
        //保存住户房屋关系,逻辑删除相关历史数据
        if (Objects.nonEmpty(residentHouse.getResidentNo()) && Objects.nonEmpty(residentHouse.getHouseNo()) && Objects.nonNull(residentHouse.getType())) {
            List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                    .eq("houseNo", residentHouse.getHouseNo())
                    .eq("residentNo", residentHouse.getResidentNo())
                    .eq("type", residentHouse.getType())
                    .eq("deleted", false)
                    .exe();
            for (ResidentHouse dbResidentHouse : residentHouseList) {
                dbResidentHouse.setDeleted(true);
                jdbcSession.updateById(dbResidentHouse);
            }
        }

        // 生成拥有者编号
        List<ResidentHouse> residentHouseList =
                jdbcSession.findArray(ResidentHouse.class)
                        .eq("communityNo", residentHouse.getCommunityNo())
                        .eq("residentNo", residentHouse.getResidentNo())
                        .eq("houseType", residentHouse.getHouseType().getId()).exe(false);
        if (Objects.nonEmpty(residentHouseList)) {
            for (ResidentHouse each : residentHouseList) {
                String ownerNo = each.getOwnerNo();
                if (!Objects.isBlank(ownerNo)) {
                    residentHouse.setOwnerNo(ownerNo);
                    break;
                }
            }
        }
        if (Objects.isBlank(residentHouse.getOwnerNo())) {
            SnowflakeIdUtils snowflakeIdUtils = new SnowflakeIdUtils(0);
            long id = snowflakeIdUtils.nextId();
            residentHouse.setOwnerNo(residentHouse.getHouseType().getCode() + id);
        }

        jdbcSession.insert(residentHouse);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentHouse);
        }
        return residentHouse;
    }


    /**
     * 绑定房屋
     * 前段微信会员认证房屋申请审核通过会触发该结果
     * 1.房屋没有绑定过任何住户,增加住户信息，增加房屋绑定记录
     * 2.房屋只有一条记录,更新住户信息，更新房屋绑定记录,删除微信会员那边不是自己绑定的微信房屋绑定记录(来源系统初始化,其他微信会员绑定了)
     * 3.房屋只有超过1条记录的记录,如果有绑定的记录则更新住户信息，更新房屋绑定记录，删除微信会员那边不是自己绑定的微信房屋绑定记录,没有则增加住户信息，增加房屋绑定记录
     * 失效
     *
     * @param residentHouse 住户房屋对象
     * @return 住户对象
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @ReqMapping("/bindResidentHouse")
    @Override
    public Resident bindResidentHouse(ResidentHouse residentHouse, JSONObject jsonObject) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentHouse);
        }


        //todo 传入枚举获取不到数据只能这样写
        //设置住户类型
        ResidentType type = EnumUtil.getEnum(ResidentType.class, jsonObject.getString("type"));
        residentHouse.setType(type);

        //设置房屋类型
        HouseType houseType = EnumUtil.getEnum(HouseType.class, jsonObject.getString("houseType"));
        residentHouse.setHouseType(houseType);


        String companyNo = residentHouse.getCompanyNo();

        Resident resident = null;
        //如果家属和租户审核通过创建或更新住户信息，然后绑定房屋
        if (!Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
            resident = Pool.newInstance(Resident.class);
            resident.setRealname(residentHouse.getRealname());
            resident.setType(residentHouse.getType());
            resident.setMobile(residentHouse.getMobile());
            saveResident(resident);
            residentHouse.setBindType(BindType.BIND);
            residentHouse.setBindTime(LocalDateTime.now());
            saveResidentHouse(residentHouse);
            resident = getResidentById(resident.getId());
            return resident;
        }

        //查询当前房屋下面的住户信息
        List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                .eq("type", ResidentType.OWNER.getId())
                .eq("houseNo", residentHouse.getHouseNo())
                .eq("deleted", false)
                .exe();
        //如果当前房屋下面没有任何住户数据，则新增住户数据并且绑定，否则有绑定记录更新数据,
        if (Objects.isEmpty(residentHouseList)) {
            resident = Pool.newInstance(Resident.class);
            resident.setRealname(residentHouse.getRealname());
            resident.setType(residentHouse.getType());
            resident.setMobile(residentHouse.getMobile());
            saveResident(resident);
            residentHouse.setResidentNo(resident.getId());
            residentHouse.setBindType(BindType.BIND);
            residentHouse.setBindTime(LocalDateTime.now());
            saveResidentHouse(residentHouse);
            bindHouse(companyNo, residentHouse);
            resident = getResidentById(resident.getId());
            return resident;
        }

        //初始化房屋绑定信息，是没有绑定的
        if (residentHouseList.size() == 1) {
            residentHouse = residentHouseList.get(0);
            residentHouse.setBindType(BindType.BIND);
            residentHouse.setBindTime(LocalDateTime.now());
            updateResidentHouse(residentHouse);
            resident = getResidentById(residentHouse.getResidentNo());
            resident.setRealname(residentHouse.getRealname());
            resident.setType(residentHouse.getType());
            resident.setMobile(residentHouse.getMobile());
            updateResident(resident);
        } else {
            //房屋住户是否存在绑定
            ResidentHouse bindResidentHouse = jdbcSession.findOne(ResidentHouse.class)
                    .eq("type", ResidentType.OWNER.getId())
                    .eq("bind", true)
                    .eq("houseNo", residentHouse.getHouseNo())
                    .eq("deleted", false)
                    .exe();

            //前房屋下面的没有绑定过住户信息
            if (Objects.nonNull(bindResidentHouse)) {
                residentHouse = bindResidentHouse;
                residentHouse.setBindType(BindType.BIND);
                residentHouse.setBindTime(LocalDateTime.now());
                updateResidentHouse(residentHouse);
                resident = getResidentById(residentHouse.getResidentNo());
                resident.setRealname(residentHouse.getRealname());
                resident.setType(residentHouse.getType());
                resident.setMobile(residentHouse.getMobile());
                updateResident(resident);
            } else {
                resident = Pool.newInstance(Resident.class);
                resident.setRealname(residentHouse.getRealname());
                resident.setType(residentHouse.getType());
                resident.setMobile(residentHouse.getMobile());
                saveResident(resident);
                residentHouse.setResidentNo(resident.getId());
                residentHouse.setBindType(BindType.BIND);
                residentHouse.setBindTime(LocalDateTime.now());
                saveResidentHouse(residentHouse);
            }
        }
        bindHouse(companyNo, residentHouse);
        resident = getResidentById(resident.getId());
        return resident;
    }


    /**
     * 认证通过绑定房屋
     * 一个房屋下面可有多个租户和家属
     * 一个房屋下面只能有一个业主
     * 1.物业不存在当前申请人申请房屋的绑定数据(未绑定,已绑定)直接新增住户绑定
     * 2.物业存在申请房屋的绑定数据(未绑定,已绑定)并且数据所属人与当前申请人是一个人则更新住户绑定数据
     * 3.物业存在申请房屋的绑定数据(未绑定,已绑定),数据所属人与当前申请人不是一个人，如果是未绑定更新成已失效,已绑定更新为已解绑，然后新增住户绑定
     *
     * @param residentHouseBindApply 住户房屋绑定申请对象
     * @return 住户对象
     * @throws Exception 操作异常
     */
    public Resident bindResidentHouse(ResidentHouseBindApply residentHouseBindApply) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentHouseBindApply);
        }

        //存在用户认证登录账号不同,认证手机号相同,则标记历史住户为已失效
        Resident oldResident = jdbcSession.findOne(Resident.class)
                .eq("mobile", residentHouseBindApply.getMobile())
                .noEq("id", residentHouseBindApply.getResidentNo())
                .eq("deleted", false).exe();

        if (Objects.nonNull(oldResident)) {
            //手机号一致,账号不一致,认证真实姓名与已存在的住户真实姓名不一致(住户占用的手机号被运营商回收的场景,后台强制审核通过)
            if (!Objects.equal(oldResident.getRealname(), residentHouseBindApply.getRealname())) {
                oldResident.setMobile(oldResident.getMobile() + "(已失效)");
                oldResident.setMobileValid(false);
                jdbcSession.updateById(oldResident);
                //级联批量修改房屋已绑定业主是当前住户的资料
                batchUpdateHouseOwner(oldResident);
                //级联批量修改商铺已绑定业主是当前住户的资料
                batchUpdateShopOwner(oldResident);
                //级联批量修改住户房屋的住户资料
                batchUpdateResidentHouse(oldResident);
                //更新已存在住户对应账号的手机号有效状态为已失效
                JSONObject body = new JSONObject();
                body.put("id", oldResident.getId());
                body.put("mobileValid", false);
                updateAccount(body);
            } else {
                //手机号一致,账号不一致,认证真实姓名与已存在的住户真实姓名一致(同一个人不同不同手机号绑定记录迁移)设置申请人手机号为当前登录账号手机号,如果数据库住户表存在账号手机号的数据则做失效动作
                oldResident = jdbcSession.findOne(Resident.class)
                        .eq("mobile", residentHouseBindApply.getAccountMobile())
                        .noEq("id", residentHouseBindApply.getResidentNo())
                        .eq("deleted", false).exe();

                if (Objects.nonNull(oldResident)) {
                    oldResident.setMobile(oldResident.getMobile() + "(已失效)");
                    oldResident.setMobileValid(false);
                    jdbcSession.updateById(oldResident);
                    //级联批量修改房屋已绑定业主是当前住户的资料
                    batchUpdateHouseOwner(oldResident);

                    //级联批量修改店铺已绑定业主是当前住户的资料
                    batchUpdateShopOwner(oldResident);

                    //级联批量修改住户房屋的住户资料
                    batchUpdateResidentHouse(oldResident);
                    //更新已存在住户对应账号的手机号有效状态为已失效
                    JSONObject body = new JSONObject();
                    body.put("id", oldResident.getId());
                    body.put("mobileValid", false);
                    updateAccount(body);
                }
                residentHouseBindApply.setMobile(residentHouseBindApply.getAccountMobile());
            }


        }

        //申请人的住户编号就是账号编号
        Resident resident = saveOrUpdateResident(residentHouseBindApply);
        //未绑定或已绑定状态集合
        List<String> bindTypeList = new ArrayList<>();
        bindTypeList.add(BindType.NO_BIND.getId());
        bindTypeList.add(BindType.BIND.getId());

        //如果家属和租户审核通过创建或更新住户信息，然后绑定房屋或更新房屋(没有数据就新增有数据就更新)(家属)
        if (!Objects.equal(residentHouseBindApply.getType().getId(), ResidentType.OWNER.getId())) {

            //查询亲属或租客在当前房屋是否已经存在绑定记录
            ResidentHouse bindResidentHouse = jdbcSession.findOne(ResidentHouse.class)
                    .eq("residentNo", residentHouseBindApply.getResidentNo())
                    .eq("houseNo", residentHouseBindApply.getHouseNo())
                    .eq("type", residentHouseBindApply.getType())
                    .in("bindType", bindTypeList)
                    .eq("deleted", false)
                    .exe();
            //不存关联数据则直接新增
            if (Objects.isNull(bindResidentHouse)) {
                ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(residentHouseBindApply);
                residentHouse.setBindType(BindType.BIND);
                residentHouse.setBindTime(LocalDateTime.now());
                saveResidentHouse(residentHouse);
            } else {
                //存在未绑定或已绑定的数据更新住户房屋绑定数据
                bindResidentHouse.setAvatar(residentHouseBindApply.getAvatar());
                bindResidentHouse.setRealname(residentHouseBindApply.getRealname());
                bindResidentHouse.setMobile(residentHouseBindApply.getMobile());
                bindResidentHouse.setBindType(BindType.BIND);
                bindResidentHouse.setBindTime(LocalDateTime.now());
                bindResidentHouse.setRelationType(residentHouseBindApply.getRelationType());
                bindResidentHouse.setStartTime(residentHouseBindApply.getStartTime());
                bindResidentHouse.setEndTime(residentHouseBindApply.getEndTime());
                updateResidentHouse(bindResidentHouse);
            }
            resident = getResidentById(resident.getId());
            //更新真实姓名
            JSONObject body = new JSONObject();
            body.put("id",resident.getId());
            body.put("realname", resident.getRealname());
            updateAccount(body);
            return resident;
        }

        //如果是业主

        //业主可能出现的情况 未录入 已录入未绑定 已录入已绑定 已录入已解绑 已录入已转让

        //查询申请房屋是否存在,已绑定未认证(未绑定状态),已经绑定已认证(已绑定)的业主房屋绑定关系信息
        String assetsType = residentHouseBindApply.getHouseType().getId();
        ResidentHouse houseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                .eq("houseNo", residentHouseBindApply.getHouseNo())
                .eq("type", ResidentType.OWNER)
                .in("bindType", bindTypeList)
                .eq("deleted", false)
                .exe();
        //不存关联业主数据则直接新增
        if (Objects.isNull(houseBindOwner)) {
            //如果当前房屋没有任何业主绑定记录则建立绑定
            ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(residentHouseBindApply);
            residentHouse.setBindType(BindType.BIND);
            residentHouse.setBindTime(LocalDateTime.now());
            saveResidentHouse(residentHouse);
            //跟进认证不同资产类型会写资产业主信息

            if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                updateOwnerHouseResult(residentHouse);
            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                updateOwnerShopResult(residentHouse);
            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                updateOwnerParkingResult(residentHouse);
            }
        } else {
            //当前房屋绑定状态的业主与当前申请的业主住户编号一致则更新住户房屋及业主绑定信息
            if (Objects.equal(houseBindOwner.getResidentNo(), residentHouseBindApply.getResidentNo())) {
                houseBindOwner.setAvatar(residentHouseBindApply.getAvatar());
                houseBindOwner.setRealname(residentHouseBindApply.getRealname());
                houseBindOwner.setMobile(residentHouseBindApply.getMobile());
                houseBindOwner.setBindType(BindType.BIND);
                houseBindOwner.setBindTime(LocalDateTime.now());
                updateResidentHouse(houseBindOwner);
                if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                    updateOwnerHouseResult(houseBindOwner);
                } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                    updateOwnerShopResult(houseBindOwner);
                } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                    updateOwnerParkingResult(houseBindOwner);
                }
            } else {
                //未绑定或已绑定的业主数据不是当前申请人,未绑定的数据更新为已失效,已绑定的数据更新为已解绑
                if (Objects.equal(houseBindOwner.getBindType().getId(), BindType.NO_BIND.getId())) {
                    houseBindOwner.setBindType(BindType.INVALID);
                    houseBindOwner.setUnBindTime(LocalDateTime.now());
                    jdbcSession.updateById(houseBindOwner);
                } else if (Objects.equal(houseBindOwner.getBindType().getId(), BindType.BIND.getId())) {
                    houseBindOwner.setBindType(BindType.UN_BIND);
                    houseBindOwner.setUnBindTime(LocalDateTime.now());
                    jdbcSession.updateById(houseBindOwner);
                }
                //解绑业主下面的租客和家属,未绑定的数据更新为已失效,已绑定的数据更新为已解绑
                List<String> residentTypeList = new ArrayList<>();
                residentTypeList.add(ResidentType.FRIEND.getId());
                residentTypeList.add(ResidentType.LESSEE.getId());
                List<ResidentHouse> noBindResidentHouseList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("houseNo", houseBindOwner.getHouseNo())
                        .in("type", residentTypeList)
                        .in("bindType", bindTypeList)
                        .eq("deleted", false)
                        .exe();
                for (ResidentHouse noBindResidentHouse : noBindResidentHouseList) {
                    if (Objects.equal(noBindResidentHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                        noBindResidentHouse.setBindType(BindType.INVALID);
                        noBindResidentHouse.setUnBindTime(LocalDateTime.now());
                    } else if (Objects.equal(noBindResidentHouse.getBindType().getId(), BindType.BIND.getId())) {
                        noBindResidentHouse.setBindType(BindType.UN_BIND);
                        noBindResidentHouse.setUnBindTime(LocalDateTime.now());
                    }
                    jdbcSession.updateById(noBindResidentHouse);
                }

                //更改审核中的申请记录为已否决
                List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                        .eq("auditNo", houseBindOwner.getResidentNo())
                        .eq("houseNo", houseBindOwner.getHouseNo())
                        .eq("status", AuditStatus.PendingAudit)
                        .eq("deleted", false).exe();
                for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                    historyResidentHouseBindApply.setStatus(AuditStatus.FailPassAudit);
                    historyResidentHouseBindApply.setAuditNo(Root.ROOT_ID);
                    historyResidentHouseBindApply.setAuditName("系统管理员");
                    historyResidentHouseBindApply.setAuditRemarks("房屋业主变更,更改审核中的申请记录为已否决");
                    jdbcSession.updateById(historyResidentHouseBindApply);
                }


                //绑定新的业主信息
                ResidentHouse residentHouse = residentAssetsService.buildResidentHouse(residentHouseBindApply);
                residentHouse.setBindType(BindType.BIND);
                residentHouse.setBindTime(LocalDateTime.now());
                saveResidentHouse(residentHouse);
                if (Objects.equal(HouseType.HOUSE.getId(),assetsType)) {
                    updateOwnerHouseResult(residentHouse);
                } else if (Objects.equal(HouseType.SHOP.getId(),assetsType)) {
                    updateOwnerShopResult(residentHouse);
                } else if (Objects.equal(HouseType.PARKING.getId(),assetsType)) {
                    updateOwnerParkingResult(residentHouse);
                }
            }
        }
        resident = getResidentById(resident.getId());
        //更新真实姓名
        JSONObject body = new JSONObject();
        body.put("id",resident.getId());
        body.put("realname", resident.getRealname());
        updateAccount(body);
        //录入不是当前申请人的未绑定数据暂时不做处理
        return resident;
    }

    /**
     * 更新账户信息
     *
     * @param body 更新内容
     * @throws Exception 异常
     */
    private void updateAccount(JSONObject body) throws Exception {
        JSONObject updateAccountResult = doveClient.post("/auth/account/service/update", (http) -> {
            http.setBody(body.toJSONString());
        });
        if (updateAccountResult.getIntValue("code") != 200) {
            logger.error("ResidentServiceImpl.updateAccount 更新住户对应的账户信息.后续修复数据一致性");
        }
    }

    /**
     * 根据房屋绑定申请新增或更新住户信息
     */
    private Resident saveOrUpdateResident(ResidentHouseBindApply residentHouseBindApply) throws Exception {
        Resident resident = getResidentById(residentHouseBindApply.getResidentNo());
        if (Objects.isNull(resident)) {
            resident = Pool.newInstance(Resident.class, residentHouseBindApply.getResidentNo());
            resident.setRealname(residentHouseBindApply.getRealname());
            resident.setType(residentHouseBindApply.getType());
            resident.setMobile(residentHouseBindApply.getMobile());
            resident.setAvatar(residentHouseBindApply.getAvatar());
            resident.setGender(Gender.NOMORE);
            //设置首字母
            resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getRealname()));
            jdbcSession.insert(resident);
        } else {
            resident.setRealname(residentHouseBindApply.getRealname());
            resident.setType(residentHouseBindApply.getType());
            resident.setMobile(residentHouseBindApply.getMobile());
            resident.setAvatar(residentHouseBindApply.getAvatar());
            //设置首字母
            resident.setFirstLetter(FirstLetterUtil.getFirstName(resident.getRealname()));
            jdbcSession.updateById(resident);

            //级联批量修改房屋已绑定业主是当前住户的资料
            batchUpdateHouseOwner(resident);

            //级联批量修改商铺已绑定业主是当前住户的资料
            batchUpdateShopOwner(resident);

            //级联批量修改住户房屋的住户资料
            batchUpdateResidentHouse(resident);
        }
        return resident;
    }

    /**
     * 绑定房屋更新住户信息
     *
     * @param residentHouse 住户房屋
     */
    private void bindHouse(String companyNo, ResidentHouse residentHouse) throws Exception {
        //增加住户如果是住户则更新房屋默认住户信息
        if (Objects.equal(residentHouse.getType().getId(), ResidentType.OWNER.getId())) {
            JSONObject houseResult = doveClient.post("/basic/house/service/update", (http) -> {
                http.addHeader("companyNo", companyNo);
                http.addParam("ownerNo", residentHouse.getResidentNo());
                http.addParam("ownerName", residentHouse.getRealname());
                http.addParam("ownerMobile", residentHouse.getMobile());
            });
            if (houseResult.getIntValue("code") != 200) {
                logger.error("ResidentServiceImpl.saveResident 回写房屋住户信息失败.后续修复数据一致性");
            }
        }
    }


    /**
     * 更新住户房屋
     *
     * @param residentHouse 住户房屋对象
     * @return 住户房屋对象
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    @ReqMapping("/updateResidentHouse")
    @Override
    public ResidentHouse updateResidentHouse(ResidentHouse residentHouse) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + residentHouse);
        }
        jdbcSession.updateById(residentHouse);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentHouse);
        }
        return residentHouse;
    }

    /**
     * 解除住户绑定房屋
     *
     * @param residentNo 住户编号
     * @param houseNo    房屋编号
     * @return 住户房屋对象
     * @throws Exception 移除
     */
    @ReqMapping("/unbindResidentHouse")
    @Override
    public Object unbindResidentHouse(String residentNo, String houseNo) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:residentNo{},houseNo:{}", residentNo, houseNo);
        }
        ResidentHouse residentHouse = jdbcSession.findOne(ResidentHouse.class)
                .eq("residentNo", residentNo)
                .eq("houseNo", houseNo)
                .eq("bindType", BindType.BIND)
                .eq("deleted", false).exe();
        if (Objects.isNull(residentHouse)) {
            return Result.error(0, "不存在当前参数下的房屋绑定信息.");
        }
        residentHouse.setBindType(BindType.UN_BIND);
        residentHouse.setUnBindTime(LocalDateTime.now());
        jdbcSession.updateById(residentHouse);
        if (logger.isDebugEnabled()) {
            logger.debug("result:" + residentHouse);
        }
        return residentHouse;
    }


    /***
     * 根据住户房屋标志删除住户房屋信息
     * @param id 住户房屋标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentHouseById")
    @Override
    public Boolean deleteResidentHouseById(String id) throws Exception {
        boolean flag = false;
        if (logger.isDebugEnabled()) {
            logger.debug("parameter:" + id);
        }
        if (!Objects.isEmpty(id)) {
            ResidentHouse result = Pool.get(ResidentHouse.class, id);
            if (result != null) {
                jdbcSession.deleteById(result);
                flag = true;
            }
        }
        return flag;
    }


    /***
     * 根据条件删除住户房屋信息
     * id   必传,type为 “1”业主身份的住户编号,type为 “1”业主身份的住户编号,type 为 “2” 家属的住户房屋编号,type 为 “3” 租客的住户房屋编号
     * type 必传,1业主 2.家属 3.租客
     * houseNo 如果删除业主下某个资产信息必须传入
     * 使用场景描述
     * 1.type为 “1” 删除业主,家属绑定记录,及申请认证记录
     * 2.type为 “2” 删除家属绑定记录,及申请认证记录
     * 3.type为 “3” 删除租户绑定记录,及申请认证记录
     * @param jsonObject 删除哦啊见
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/deleteResidentHouse")
    @Override
    public Boolean deleteResidentHouse(JSONObject jsonObject) throws Exception {
        boolean flag = false;
        //类型为1则id是住户编号 类型为2则住户房屋绑定编号 类型为3住户房屋绑定编号
        String type = jsonObject.getString("type");
        String id = jsonObject.getString("id");
//        String houseNo = jsonObject.getString("houseNo");
        if (Objects.nonEmpty(id) && Objects.nonEmpty(type)) {
            if (Objects.equal(type, ResidentType.OWNER.getId())) {
                //查询业主未绑定及已绑定的房屋绑定数据
                List<String> bindTypeList = new ArrayList<>();
                bindTypeList.add(BindType.NO_BIND.getId());
                bindTypeList.add(BindType.BIND.getId());
                List<ResidentHouse> ownerHouseList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("residentNo", id)
                        .eq("type", ResidentType.OWNER)
                        .in("bindType", bindTypeList)
                        .eq("deleted", false)
                        .eq(jsonObject, "houseNo","communityNo").exe();
                for (ResidentHouse ownerHouse : ownerHouseList) {
                    //增量解绑当前住户未认证业主身份下面所有未绑定房屋,级联解除业主下面的租客和家属
                    if (Objects.equal(ownerHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                        ownerHouse.setBindType(BindType.INVALID);
                        ownerHouse.setUnBindTime(LocalDateTime.now());
                        ownerHouse.setDeleted(true);
                        jdbcSession.updateById(ownerHouse);
                    } else if (Objects.equal(ownerHouse.getBindType().getId(), BindType.BIND.getId())) {
                        ownerHouse.setBindType(BindType.UN_BIND);
                        ownerHouse.setUnBindTime(LocalDateTime.now());
                        ownerHouse.setDeleted(true);
                        jdbcSession.updateById(ownerHouse);
                    } else {
                        ownerHouse.setDeleted(true);
                        jdbcSession.updateById(ownerHouse);
                    }

                    //解绑房屋绑定的业主信息
                    ResidentHouse removeHouseOwner = Pool.newInstance(ResidentHouse.class);
                    removeHouseOwner.setHouseNo(ownerHouse.getHouseNo());
                    removeHouseOwner.setResidentNo("");
                    removeHouseOwner.setRealname("");
                    removeHouseOwner.setMobile("");
                    updateOwnerHouseResult(removeHouseOwner);


                    //解绑业主下面的租客和家属
                    List<String> typeList = new ArrayList<>();
                    typeList.add(ResidentType.FRIEND.getId());
                    typeList.add(ResidentType.LESSEE.getId());
                    List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                            .eq("houseNo", ownerHouse.getHouseNo())
                            .in("type", typeList)
                            .in("bindType", bindTypeList)
                            .eq("deleted", false)
                            .exe();
                    for (ResidentHouse residentHouse : residentHouseList) {
                        if (Objects.equal(residentHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                            residentHouse.setBindType(BindType.INVALID);
                            residentHouse.setUnBindTime(LocalDateTime.now());
                            residentHouse.setDeleted(true);
                            jdbcSession.updateById(residentHouse);
                        } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId())) {
                            residentHouse.setBindType(BindType.UN_BIND);
                            residentHouse.setUnBindTime(LocalDateTime.now());
                            residentHouse.setDeleted(true);
                            jdbcSession.updateById(residentHouse);
                        } else {
                            residentHouse.setDeleted(true);
                            jdbcSession.updateById(ownerHouse);
                        }
                    }

                    //更改属于业主审核中的申请记录为已否决
                    List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                            .eq("auditNo", ownerHouse.getResidentNo())
                            .eq("houseNo", ownerHouse.getHouseNo())
                            .eq("status", AuditStatus.PendingAudit)
                            .eq("deleted", false).exe();
                    for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                        historyResidentHouseBindApply.setStatus(AuditStatus.FailPassAudit);
                        historyResidentHouseBindApply.setAuditNo(Root.ROOT_ID);
                        historyResidentHouseBindApply.setAuditName("系统管理员");
                        historyResidentHouseBindApply.setAuditRemarks("房屋业主删除,更改审核中的申请记录为已否决");
                        jdbcSession.updateById(historyResidentHouseBindApply);
                    }
                }

            } else if (Objects.equal(type, ResidentType.FRIEND.getId())) {
                ResidentHouse residentHouse = getResidentHouseById(id);
                if (Objects.equal(residentHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                    residentHouse.setBindType(BindType.INVALID);
                    residentHouse.setUnBindTime(LocalDateTime.now());
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId())) {
                    residentHouse.setBindType(BindType.UN_BIND);
                    residentHouse.setUnBindTime(LocalDateTime.now());
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                } else {
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                }
                //逻辑删除当前房屋的申请记录
                /*List<ResidentHouseBindApply> residentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                        .eq("residentNo", residentHouse.getResidentNo())
                        .eq("type", ResidentType.FRIEND)
                        .eq("houseNo", residentHouse.getHouseNo())
                        .eq("deleted", false).exe();
                for (ResidentHouseBindApply residentHouseBindApply : residentHouseBindApplyList) {
                    residentHouseBindApply.setDeleted(true);
                    jdbcSession.updateById(residentHouseBindApply);
                }*/

            } else if (Objects.equal(type, ResidentType.LESSEE.getId())) {
                ResidentHouse residentHouse = getResidentHouseById(id);
                if (Objects.equal(residentHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                    residentHouse.setBindType(BindType.INVALID);
                    residentHouse.setUnBindTime(LocalDateTime.now());
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId())) {
                    residentHouse.setBindType(BindType.UN_BIND);
                    residentHouse.setUnBindTime(LocalDateTime.now());
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                } else {
                    residentHouse.setDeleted(true);
                    jdbcSession.updateById(residentHouse);
                }
                //逻辑删除当前房屋的申请记录
               /* List<ResidentHouseBindApply> residentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                        .eq("residentNo", residentHouse.getResidentNo())
                        .eq("type", ResidentType.LESSEE)
                        .eq("houseNo", residentHouse.getHouseNo())
                        .eq("deleted", false).exe();
                for (ResidentHouseBindApply residentHouseBindApply : residentHouseBindApplyList) {
                    residentHouseBindApply.setDeleted(true);
                    jdbcSession.updateById(residentHouseBindApply);
                }*/
            }
            flag = true;
        }
        return flag;
    }

    /***
     * 根据条件批量删除住户房屋信息
     * 1.业主列表删除
     * 2.亲属列表删除
     * 3.租户列表删除
     * @param jsonObject 删除哦啊见
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/batchDeleteResidentHouse")
    @Override
    public Boolean batchDeleteResidentHouse(JSONObject jsonObject) throws Exception {
        boolean flag = false;
        JSONArray deleteList = jsonObject.getJSONArray("array");
        if (Objects.nonEmpty(deleteList)) {
            for (int i = 0; i < deleteList.size(); i++) {
                JSONObject json = deleteList.getJSONObject(i);
                flag = deleteResidentHouse(json);
                //删除房屋历史绑定的信息
                String houseNo = json.getString("houseNo");
                if (Objects.nonEmpty(houseNo)) {
                    List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                            .eq("houseNo", houseNo)
                            .eq("deleted", false).exe();
                    for (ResidentHouse residentHouse : residentHouseList) {
                        residentHouse.setDeleted(true);
                    }
                    jdbcSession.updateById(residentHouseList);
                }
            }
        }
        return flag;
    }

    /**
     * 导出住户数据文件
     *
     * @param residentList 住户数据集合
     * @return 文件对象
     * @throws Exception
     */
    @ReqMapping("/exportResidentDataFile")
    @Override
    public File exportResidentDataFile(List<Resident> residentList) throws Exception {
        Workbook wb = exportWorkBook(residentList);
        return ExcelUtil.writeXlsFile(wb, "住户列表", ".xls");
    }


    private Workbook exportWorkBook(List<Resident> residentList) throws Exception{
        JSONObject tagGroupResult = doveClient.post("/crm/tag/getTagList", (http) -> {
            JSONObject body = new JSONObject();
            body.put("group", true);
            body.put("pageSize", Short.MAX_VALUE);
            http.setBody(body.toJSONString());
        });
        JSONArray tagGroupList = tagGroupResult.getJSONObject("data").getJSONArray("list");

        Map<String,String> tagMapping=new LinkedHashMap<>();
        JSONObject tagResult = doveClient.post("/crm/tag/getTagList", (http) -> {
            JSONObject body = new JSONObject();
            body.put("group", false);
            body.put("pageSize", Short.MAX_VALUE);
            http.setBody(body.toJSONString());
        });
        JSONArray tagList = tagResult.getJSONObject("data").getJSONArray("list");
        if (Objects.nonEmpty(tagList)) {
            for (Object tagObj : tagList) {
                JSONObject tag = (JSONObject) tagObj;
                tagMapping.put(tag.getString("id"),tag.getString("pid"));
            }
        }


        //Todo 动态生成标签
        List<String> chargeUserInstrumentList=new ArrayList<>();
        chargeUserInstrumentList.add("姓名");
        chargeUserInstrumentList.add("昵称");
        chargeUserInstrumentList.add("手机");
        chargeUserInstrumentList.add("备注名");
        chargeUserInstrumentList.add("跟进员工");
        chargeUserInstrumentList.add("客户分类");
        if (Objects.nonEmpty(tagGroupList)) {
            for (Object tagGroupObj : tagGroupList) {
                JSONObject tagGroup = (JSONObject) tagGroupObj;
                chargeUserInstrumentList.add(tagGroup.getString("name"));
            }
        }
        chargeUserInstrumentList.add("添加时间");



        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建工具
        CreationHelper helper = wb.getCreationHelper();
        //单元格样式类
        CellStyle dateCellStyle = wb.createCellStyle();
        //设置单元格格式
        dateCellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
       /* String[] chargeUserInstrument = {"客户姓名", "客户昵称", "手机", "跟进员工", "客户分类", "客户标签", "添加时间"};
        for (String s : chargeUserInstrument) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }*/
        for (String s : chargeUserInstrumentList) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }
        int cellNum = 0;
        for (int i = 0; i < residentList.size(); i++) {
            Resident resident = residentList.get(i);
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            row.createCell(cellNum++).setCellValue(resident.getRealname());
            row.createCell(cellNum++).setCellValue(resident.getNickname());
            row.createCell(cellNum++).setCellValue(resident.getMobile());
            row.createCell(cellNum++).setCellValue(resident.getRemark());
            StringBuilder userName = new StringBuilder();
            resident.getUsers().forEach(item -> {
                userName.append(item + " ");
            });
            row.createCell(cellNum++).setCellValue(userName.toString());
            row.createCell(cellNum++).setCellValue(resident.getClassifyName());
            if (Objects.nonEmpty(tagGroupList)) {
                for (Object tagGroupObj : tagGroupList) {
                    JSONObject tagGroup = (JSONObject) tagGroupObj;
                    StringBuilder tagName = new StringBuilder();
                    List<String> tagIds=resident.getTagIds();
                    for(int x=0;x<tagIds.size();x++){
                        String tagId=tagIds.get(x);
                        if(tagMapping.containsKey(tagId) && Objects.equal(tagMapping.get(tagId),tagGroup.getString("id"))){
                            tagName.append(resident.getTagNames().get(x) + " ");
                        }
                    }
                    row.createCell(cellNum++).setCellValue(tagName.toString());
                }
            }
/*            StringBuilder tagName = new StringBuilder();
            resident.getTagNames().forEach(item -> {
                tagName.append(item + " ");
            });
            row.createCell(cellNum++).setCellValue(tagName.toString());*/

            Cell tmpCell = row.createCell(cellNum++);
            tmpCell.setCellStyle(dateCellStyle);
            tmpCell.setCellValue(resident.getCreateTime());
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }


    /**
     * 设置跟进人信息
     *
     * @param userId   用户ID
     * @param userName 用户名称
     * @param resident 住户信息
     */
    private void setUsers(String userId, String userName, Resident resident) {
        if (Objects.isEmpty(userId) || Objects.isEmpty(userName) || Objects.isNull(resident)) {
            return;
        }
        List<String> dbUsers = resident.getUsers();
        List<String> dbUserNames = resident.getUserNames();
        if (Objects.isEmpty(dbUsers)) {
            dbUsers = new ArrayList<>();
            dbUserNames = new ArrayList<>();
            dbUsers.add(userId);
            dbUserNames.add(userName);

        } else {
            if (!dbUsers.contains(userId)) {
                dbUsers.add(userId);
                dbUserNames.add(userName);
            }
        }
        resident.setUsers(dbUsers);
        resident.setUserNames(dbUserNames);

    }


    /**
     * 新增或变更房屋业信息
     *
     * @param resident 住户对象
     * @return 结果
     * @throws Exception 异常
     */
    @ReqMapping("/saveOrUpdateHouseOwner")
    @Override
    public Object saveOrUpdateHouseOwner(Resident resident) throws Exception {

        List<Resident> residentList = jdbcSession.findArray(Resident.class)
                .eq("mobile", resident.getMobile())
                .eq("deleted", false)
                .order("createTime", "desc")
                .exe();
        Resident dbResident = null;
        if (Objects.nonEmpty(residentList)) {
            dbResident = residentList.get(0);
            logger.info("begin=============================================saveOrUpdateHouseOwner：{}",dbResident.toJSON());
            dbResident.setCardType(resident.getCardType());
            dbResident.setCardNo(resident.getCardNo());
            dbResident.setBirthDay(resident.getBirthDay());
            dbResident.setWeixinNo(resident.getWeixinNo());
            dbResident.setEmail(resident.getEmail());
            dbResident.setAddress(resident.getAddress());
            dbResident.setOfferName(resident.getOfferName());
            dbResident.setRemark(resident.getRemark());
            //级联更新资产业务信息
            updateResident(dbResident);
            //jdbcSession.updateById(dbResident);
            logger.info("end=============================================saveOrUpdateHouseOwner：{}",dbResident.toJSON());
        }
        //如果当前房屋已经被小程序认证审核通过则忽略当前数据
        ResidentHouse residentHouseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                .eq("houseNo", resident.getHouseNo())
                .eq("type", ResidentType.OWNER)
                .eq("bindType", BindType.BIND.getId())
                .eq("deleted", false)
                .exe();
        if (Objects.nonNull(residentHouseBindOwner)) {
            StringBuilder sb = new StringBuilder();
            sb.append(residentHouseBindOwner.getCommunityName()).append(residentHouseBindOwner.getBuildName()).append(residentHouseBindOwner.getUnitName()).append(residentHouseBindOwner.getFloorName()).append(residentHouseBindOwner.getHouseName());
            logger.info("房屋{},已绑定,不能进行操作.", sb.toString());
            return Result.success();
        }

        String assetsType = resident.getHouseType().getId();
        //通过查询数据库是否有记录判断是新增还是更新
        if (Objects.isNull(dbResident)) {
            //导入的新业主归属房屋是否被其他业主绑定(待绑定)
            ResidentHouse houseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                    .eq("houseNo", resident.getHouseNo())
                    .eq("type", ResidentType.OWNER)
                    .eq("bindType", BindType.NO_BIND.getId())
                    .eq("deleted", false)
                    .exe();
            //新业主归属房屋被其他业主临时绑定(待绑定)进行解绑操作
            if (Objects.nonNull(houseBindOwner)) {
                houseBindOwner.setBindType(BindType.INVALID);
                houseBindOwner.setUnBindTime(LocalDateTime.now());
                jdbcSession.updateById(houseBindOwner);
                //解绑业主下面的租客和家属,未绑定的数据更新为已失效
                List<String> residentTypeList = new ArrayList<>();
                residentTypeList.add(ResidentType.FRIEND.getId());
                residentTypeList.add(ResidentType.LESSEE.getId());
                List<String> bindTypeList = new ArrayList<>();
                bindTypeList.add(BindType.NO_BIND.getId());
                bindTypeList.add(BindType.BIND.getId());
                List<ResidentHouse> noOwnerHouseList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("houseNo", houseBindOwner.getHouseNo())
                        .in("type", residentTypeList)
                        .in("bindType", bindTypeList)
                        .eq("deleted", false)
                        .exe();
                for (ResidentHouse noOwnerHouse : noOwnerHouseList) {
                    if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                        noOwnerHouse.setBindType(BindType.INVALID);
                        noOwnerHouse.setUnBindTime(LocalDateTime.now());
                    } else if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.BIND.getId())) {
                        noOwnerHouse.setBindType(BindType.UN_BIND);
                        noOwnerHouse.setUnBindTime(LocalDateTime.now());
                    }
                    jdbcSession.updateById(noOwnerHouse);
                }

                //逻辑删除历史业主及其租客的这套房的认证申请记录
                //逻辑删除当前房屋历史申请记录
                //更改属于业主审核中的申请记录为已否决
                List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                        .eq("auditNo", houseBindOwner.getResidentNo())
                        .eq("houseNo", houseBindOwner.getHouseNo())
                        .eq("status", AuditStatus.PendingAudit)
                        .eq("deleted", false).exe();
                for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                    historyResidentHouseBindApply.setStatus(AuditStatus.FailPassAudit);
                    historyResidentHouseBindApply.setAuditNo(Root.ROOT_ID);
                    historyResidentHouseBindApply.setAuditName("系统管理员");
                    historyResidentHouseBindApply.setAuditRemarks("房屋业主更换,更改审核中的申请记录为已否决");
                    jdbcSession.updateById(historyResidentHouseBindApply);
                }
            }
            List<String> houseIds = new ArrayList<>();
            houseIds.add(resident.getHouseNo());
            if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                resident.setHouseIds(houseIds);
            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                resident.setShopIds(houseIds);
            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                resident.setParkingIds(houseIds);
            } else {
                resident.setHouseIds(houseIds);
            }
            saveResident(resident);
        } else {
            ResidentHouse houseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                    .eq("houseNo", resident.getHouseNo())
                    .eq("type", ResidentType.OWNER)
                    .eq("bindType", BindType.NO_BIND)
                    .eq("deleted", false)
                    .exe();
            //房屋不存关联业主数据则直接新增
            if (Objects.isNull(houseBindOwner)) {
                //查询业主所有未绑定的房屋
                List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("residentNo", dbResident.getId())
                        .eq("houseType", assetsType)
                        .eq("type", ResidentType.OWNER)
                        .eq("bindType", BindType.NO_BIND)
                        .eq("deleted", false)
                        .exe();

                Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                dbHouseNoList.add(resident.getHouseNo());
                if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                    dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                    dbResident.setShopIds(new ArrayList<>(dbHouseNoList));
                } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                    dbResident.setParkingIds(new ArrayList<>(dbHouseNoList));
                } else {
                    dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                }
                dbResident.setType(ResidentType.OWNER);
                dbResident.setCompanyNo(resident.getCompanyNo());
                dbResident.setCompanyName(resident.getCompanyName());
                updateResident(dbResident);

            } else {
                //当前房屋绑定状态的业主与当前导入的业主住户编号一致则更新住户房屋及业主绑定信息
                if (Objects.equal(houseBindOwner.getResidentNo(), dbResident.getId())) {
                    //查询业主所有未绑定的房屋
                    List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                            .eq("residentNo", dbResident.getId())
                            .eq("houseType", assetsType)
                            .eq("type", ResidentType.OWNER)
                            .eq("bindType", BindType.NO_BIND)
                            .eq("deleted", false)
                            .exe();

                    Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                    dbHouseNoList.add(resident.getHouseNo());
                    if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                        dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                    } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                        dbResident.setShopIds(new ArrayList<>(dbHouseNoList));
                    } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                        dbResident.setParkingIds(new ArrayList<>(dbHouseNoList));
                    } else {
                        dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                    }
                    dbResident.setType(ResidentType.OWNER);
                    dbResident.setCompanyNo(resident.getCompanyNo());
                    dbResident.setCompanyName(resident.getCompanyName());
                    updateResident(dbResident);
                } else {
                    houseBindOwner.setBindType(BindType.INVALID);
                    houseBindOwner.setUnBindTime(LocalDateTime.now());
                    jdbcSession.updateById(houseBindOwner);
                    //解绑业主下面的租客和家属,未绑定的数据更新为已失效
                    List<String> bindTypeList = new ArrayList<>();
                    bindTypeList.add(BindType.NO_BIND.getId());
                    bindTypeList.add(BindType.BIND.getId());
                    List<String> residentTypeList = new ArrayList<>();
                    residentTypeList.add(ResidentType.FRIEND.getId());
                    residentTypeList.add(ResidentType.LESSEE.getId());
                    List<ResidentHouse> noOwnerHouseList = jdbcSession.findArray(ResidentHouse.class)
                            .eq("houseNo", houseBindOwner.getHouseNo())
                            .in("type", residentTypeList)
                            .in("bindType", bindTypeList)
                            .eq("deleted", false)
                            .exe();
                    for (ResidentHouse noOwnerHouse : noOwnerHouseList) {
                        if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                            noOwnerHouse.setBindType(BindType.INVALID);
                            noOwnerHouse.setUnBindTime(LocalDateTime.now());
                        } else if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.BIND.getId())) {
                            noOwnerHouse.setBindType(BindType.UN_BIND);
                            noOwnerHouse.setUnBindTime(LocalDateTime.now());
                        }
                        jdbcSession.updateById(noOwnerHouse);
                    }

                    //逻辑删除历史业主及其租客的这套房的认证申请记录
                    //逻辑删除当前房屋历史申请记录
                    List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                            .eq("houseNo", houseBindOwner.getHouseNo())
                            .eq("deleted", false).exe();
                    for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                        historyResidentHouseBindApply.setDeleted(true);
                        jdbcSession.updateById(historyResidentHouseBindApply);
                    }


                    //查询业主所有未绑定的房屋
                    List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                            .eq("residentNo", dbResident.getId())
                            .eq("houseType", assetsType)
                            .eq("type", ResidentType.OWNER)
                            .eq("bindType", BindType.NO_BIND)
                            .eq("deleted", false)
                            .exe();

                    Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                    dbHouseNoList.add(resident.getHouseNo());
                    if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                        dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                    } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                        dbResident.setShopIds(new ArrayList<>(dbHouseNoList));
                    } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                        dbResident.setParkingIds(new ArrayList<>(dbHouseNoList));
                    } else {
                        dbResident.setHouseIds(new ArrayList<>(dbHouseNoList));
                    }
                    dbResident.setType(ResidentType.OWNER);
                    dbResident.setCompanyNo(resident.getCompanyNo());
                    dbResident.setCompanyName(resident.getCompanyName());
                    updateResident(dbResident);
                }
            }

        }
        return Result.success();
    }


    /**
     * 批量保存或更新业主信息
     * 当前接口必须登录才可以使用
     *
     * @param token     登录用户信息
     * @param condition 住户信息数据
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/batchSaveOrUpdateOwner")
    @Override
    public Object batchSaveOrUpdateOwner(Token token, JSONObject condition) throws Exception {
        if (Objects.isNull(token)) {
            return Result.error(0, "请先登录在进行操作");
        }
        JSONArray ownerList = condition.getJSONArray("ownerList");
        if (Objects.nonEmpty(ownerList)) {
            for (int i = 0; i < ownerList.size(); i++) {
                JSONObject jsonObject = ownerList.getJSONObject(i);
                String realname = jsonObject.getString("realname");
                String mobile = jsonObject.getString("mobile");
                String cardType = jsonObject.getString("cardType");
                String cardNo = jsonObject.getString("cardNo");
                String houseNo = jsonObject.getString("houseNo");
                String assetsType = jsonObject.getString("houseType");
                String weixinNo = jsonObject.getString("weixinNo");
                String gender = jsonObject.getString("gender");
                String birthDay = jsonObject.getString("birthDay");
                String email = jsonObject.getString("email");
                String address = jsonObject.getString("address");
                String offerName = jsonObject.getString("offerName");
                String remark = jsonObject.getString("remark");
                String relationType=jsonObject.getString("relationType");  //与业主关系
                String startTime=jsonObject.getString("startTime");       // 租赁开始时间
                String endTime=jsonObject.getString("endTime");            //租赁结束时间

                if (Objects.isEmpty(mobile) || Objects.isEmpty(houseNo)) {
                    continue;
                }
                FindOne<Resident> find = jdbcSession.findOne(Resident.class)
                        .eq(jsonObject, "id")
                        .eq("mobile", mobile)
                        .eq("deleted", false);
                Resident resident = find.exe();
                //如果当前房屋已经被小程序认证审核通过则忽略当前数据
                ResidentHouse residentHouseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                        .eq("houseNo", houseNo)
                        .eq("type", ResidentType.OWNER)
                        .eq("bindType", BindType.BIND.getId())
                        .eq("deleted", false)
                        .exe();

                if (Objects.nonNull(residentHouseBindOwner)) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(residentHouseBindOwner.getCommunityName()).append(residentHouseBindOwner.getBuildName()).append(residentHouseBindOwner.getUnitName()).append(residentHouseBindOwner.getFloorName()).append(residentHouseBindOwner.getHouseName());
                    logger.info("导入业主{},房屋{},已绑定.", residentHouseBindOwner.getRealname(), sb.toString());
                    continue;
                }


                //通过查询数据库是否有记录判断是新增还是更新
                if (Objects.isNull(resident)) {
                    //导入的新业主归属房屋是否被其他业主绑定(待绑定)
                    ResidentHouse houseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                            .eq("houseNo", houseNo)
                            .eq("type", ResidentType.OWNER)
                            .eq("bindType", BindType.NO_BIND.getId())
                            .eq("deleted", false)
                            .exe();
                    //新业主归属房屋被其他业主临时绑定(待绑定)进行解绑操作
                    if (Objects.nonNull(houseBindOwner)) {
                        houseBindOwner.setBindType(BindType.INVALID);
                        houseBindOwner.setUnBindTime(LocalDateTime.now());
                        jdbcSession.updateById(houseBindOwner);
                        //解绑业主下面的租客和家属,未绑定的数据更新为已失效
                        List<String> residentTypeList = new ArrayList<>();
                        residentTypeList.add(ResidentType.FRIEND.getId());
                        residentTypeList.add(ResidentType.LESSEE.getId());
                        List<String> bindTypeList = new ArrayList<>();
                        bindTypeList.add(BindType.NO_BIND.getId());
                        bindTypeList.add(BindType.BIND.getId());
                        List<ResidentHouse> noOwnerHouseList = jdbcSession.findArray(ResidentHouse.class)
                                .eq("houseNo", houseBindOwner.getHouseNo())
                                .in("type", residentTypeList)
                                .in("bindType", bindTypeList)
                                .eq("deleted", false)
                                .exe();
                        for (ResidentHouse noOwnerHouse : noOwnerHouseList) {
                            if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                                noOwnerHouse.setBindType(BindType.INVALID);
                                noOwnerHouse.setUnBindTime(LocalDateTime.now());
                            } else if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.BIND.getId())) {
                                noOwnerHouse.setBindType(BindType.UN_BIND);
                                noOwnerHouse.setUnBindTime(LocalDateTime.now());
                            }
                            jdbcSession.updateById(noOwnerHouse);
                        }

                        //逻辑删除历史业主及其租客的这套房的认证申请记录
                        //逻辑删除当前房屋历史申请记录
                        List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                                .eq("houseNo", houseBindOwner.getHouseNo())
                                .eq("deleted", false).exe();
                        for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                            historyResidentHouseBindApply.setDeleted(true);
                            jdbcSession.updateById(historyResidentHouseBindApply);
                        }
                    }
                    List<String> houseIds = new ArrayList<>();
                    houseIds.add(houseNo);
                    resident = Pool.newInstance(Resident.class);
                    resident.setRealname(realname);
                    resident.setMobile(mobile);
                    CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                    resident.setCardType(cardTypeEnum);
                    resident.setCardNo(cardNo);
                    if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                        resident.setHouseIds(houseIds);
                    } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                        resident.setShopIds(houseIds);
                    } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                        resident.setParkingIds(houseIds);
                    } else {
                        resident.setHouseIds(houseIds);
                    }
                    resident.setType(ResidentType.OWNER);
                    resident.setCompanyNo(token.getCompanyNo());

                    //设置额外字段
                    resident.setWeixinNo(weixinNo);
                    if(Objects.nonEmpty(gender)){
                        resident.setGender(Gender.getGender(gender));
                    }
                    if(Objects.nonEmpty(birthDay)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(birthDay,df);
                        resident.setBirthDay(val.atStartOfDay());
                    }
                    resident.setEmail(email);
                    resident.setAddress(address);
                    resident.setOfferName(offerName);
                    resident.setRemark(remark);
                    saveResident(resident);
                } else {
                    ResidentHouse houseBindOwner = jdbcSession.findOne(ResidentHouse.class)
                            .eq("houseNo", houseNo)
                            .eq("type", ResidentType.OWNER)
                            .eq("bindType", BindType.NO_BIND)
                            .eq("deleted", false)
                            .exe();
                    //房屋不存关联业主数据则直接新增
                    if (Objects.isNull(houseBindOwner)) {
                        //查询业主所有未绑定的房屋
                        List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                                .eq("residentNo", resident.getId())
                                .eq("type", ResidentType.OWNER)
                                .eq("bindType", BindType.NO_BIND)
                                .eq("houseType", assetsType)
                                .eq("deleted", false)
                                .exe();

                        Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                        dbHouseNoList.add(houseNo);

                        resident.setRealname(realname);
                        resident.setMobile(mobile);
                        CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                        resident.setCardType(cardTypeEnum);
                        resident.setCardNo(cardNo);
                        if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                            resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                        } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                            resident.setShopIds(new ArrayList<>(dbHouseNoList));
                        } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                            resident.setParkingIds(new ArrayList<>(dbHouseNoList));
                        } else {
                            resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                        }

                        resident.setType(ResidentType.OWNER);
                        resident.setCompanyNo(token.getCompanyNo());

                        //设置额外字段
                        resident.setWeixinNo(weixinNo);
                        if(Objects.nonEmpty(gender)){
                            resident.setGender(Gender.getGender(gender));
                        }
                        if(Objects.nonEmpty(birthDay)){
                            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                            LocalDate val = LocalDate.parse(birthDay,df);
                            resident.setBirthDay(val.atStartOfDay());
                        }
                        resident.setEmail(email);
                        resident.setAddress(address);
                        resident.setOfferName(offerName);
                        resident.setRemark(remark);
                        updateResident(resident);

                    } else {
                        //当前房屋绑定状态的业主与当前导入的业主住户编号一致则更新住户房屋及业主绑定信息
                        if (Objects.equal(houseBindOwner.getResidentNo(), resident.getId())) {
                            //查询业主所有未绑定的房屋
                            List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                                    .eq("residentNo", resident.getId())
                                    .eq("type", ResidentType.OWNER)
                                    .eq("bindType", BindType.NO_BIND)
                                    .eq("houseType", assetsType)
                                    .eq("deleted", false)
                                    .exe();

                            Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                            dbHouseNoList.add(houseNo);

                            resident.setRealname(realname);
                            resident.setMobile(mobile);
                            CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                            resident.setCardType(cardTypeEnum);
                            resident.setCardNo(cardNo);
                            if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                                resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                                resident.setShopIds(new ArrayList<>(dbHouseNoList));
                            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                                resident.setParkingIds(new ArrayList<>(dbHouseNoList));
                            } else {
                                resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                            }
                            resident.setType(ResidentType.OWNER);
                            resident.setCompanyNo(token.getCompanyNo());


                            //设置额外字段
                            resident.setWeixinNo(weixinNo);
                            if(Objects.nonEmpty(gender)){
                                resident.setGender(Gender.getGender(gender));
                            }
                            if(Objects.nonEmpty(birthDay)){
                                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                                LocalDate val = LocalDate.parse(birthDay,df);
                                resident.setBirthDay(val.atStartOfDay());
                            }
                            resident.setEmail(email);
                            resident.setAddress(address);
                            resident.setOfferName(offerName);
                            resident.setRemark(remark);
                            updateResident(resident);
                        } else {
                            houseBindOwner.setBindType(BindType.INVALID);
                            houseBindOwner.setUnBindTime(LocalDateTime.now());
                            jdbcSession.updateById(houseBindOwner);
                            //解绑业主下面的租客和家属,未绑定的数据更新为已失效
                            List<String> bindTypeList = new ArrayList<>();
                            bindTypeList.add(BindType.NO_BIND.getId());
                            bindTypeList.add(BindType.BIND.getId());
                            List<String> residentTypeList = new ArrayList<>();
                            residentTypeList.add(ResidentType.FRIEND.getId());
                            residentTypeList.add(ResidentType.LESSEE.getId());
                            List<ResidentHouse> noOwnerHouseList = jdbcSession.findArray(ResidentHouse.class)
                                    .eq("houseNo", houseBindOwner.getHouseNo())
                                    .in("type", residentTypeList)
                                    .in("bindType", bindTypeList)
                                    .eq("deleted", false)
                                    .exe();
                            for (ResidentHouse noOwnerHouse : noOwnerHouseList) {
                                if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.NO_BIND.getId())) {
                                    noOwnerHouse.setBindType(BindType.INVALID);
                                    noOwnerHouse.setUnBindTime(LocalDateTime.now());
                                } else if (Objects.equal(noOwnerHouse.getBindType().getId(), BindType.BIND.getId())) {
                                    noOwnerHouse.setBindType(BindType.UN_BIND);
                                    noOwnerHouse.setUnBindTime(LocalDateTime.now());
                                }
                                jdbcSession.updateById(noOwnerHouse);
                            }

                            //逻辑删除历史业主及其租客的这套房的认证申请记录
                            //逻辑删除当前房屋历史申请记录
                            List<ResidentHouseBindApply> historyResidentHouseBindApplyList = jdbcSession.findArray(ResidentHouseBindApply.class)
                                    .eq("houseNo", houseBindOwner.getHouseNo())
                                    .eq("deleted", false).exe();
                            for (ResidentHouseBindApply historyResidentHouseBindApply : historyResidentHouseBindApplyList) {
                                historyResidentHouseBindApply.setDeleted(true);
                                jdbcSession.updateById(historyResidentHouseBindApply);
                            }


                            //查询业主所有未绑定的房屋
                            List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                                    .eq("residentNo", resident.getId())
                                    .eq("type", ResidentType.OWNER)
                                    .eq("bindType", BindType.NO_BIND)
                                    .eq("houseType", assetsType)
                                    .eq("deleted", false)
                                    .exe();

                            Set<String> dbHouseNoList = residentHouseList.stream().map(ResidentHouse::getHouseNo).collect(Collectors.toSet());
                            dbHouseNoList.add(houseNo);

                            resident.setRealname(realname);
                            resident.setMobile(mobile);
                            CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                            resident.setCardType(cardTypeEnum);
                            resident.setCardNo(cardNo);
                            if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                                resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                                resident.setShopIds(new ArrayList<>(dbHouseNoList));
                            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                                resident.setParkingIds(new ArrayList<>(dbHouseNoList));
                            } else {
                                resident.setHouseIds(new ArrayList<>(dbHouseNoList));
                            }
                            resident.setType(ResidentType.OWNER);
                            resident.setCompanyNo(token.getCompanyNo());

                            //设置额外字段
                            resident.setWeixinNo(weixinNo);
                            if(Objects.nonEmpty(gender)){
                                resident.setGender(Gender.getGender(gender));
                            }
                            if(Objects.nonEmpty(birthDay)){
                                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                                LocalDate val = LocalDate.parse(birthDay,df);
                                resident.setBirthDay(val.atStartOfDay());
                            }
                            resident.setEmail(email);
                            resident.setAddress(address);
                            resident.setOfferName(offerName);
                            resident.setRemark(remark);
                            updateResident(resident);
                        }
                    }

                }

            }
        }
        return Result.success();
    }



    /**
     * 批量保存或更新家属租客信息
     * 当前接口必须登录才可以使用
     *
     * @param token     登录用户信息
     * @param condition 住户信息数据
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @ReqMapping("/batchSaveOrUpdateNoOwner")
    @Override
    public Object batchSaveOrUpdateNoOwner(Token token, JSONObject condition) throws Exception {
        if (Objects.isNull(token)) {
            return Result.error(0, "请先登录在进行操作");
        }
        String residentTypeId=condition.getString("residentType");
        //住户类型 1.业主 2.家属 3.租客
        ResidentType residentType=EnumUtil.getEnum(ResidentType.class,residentTypeId);
        if(Objects.equal(residentType.getId(),ResidentType.OWNER.getId())){
            return Result.error(0, "不支持业主导入");
        }

        JSONArray ownerList = condition.getJSONArray("ownerList");
        if (Objects.nonEmpty(ownerList)) {
            for (int i = 0; i < ownerList.size(); i++) {
                JSONObject jsonObject = ownerList.getJSONObject(i);
                String realname = jsonObject.getString("realname");
                String mobile = jsonObject.getString("mobile");
                String cardType = jsonObject.getString("cardType");
                String cardNo = jsonObject.getString("cardNo");
                String houseNo = jsonObject.getString("houseNo");
                String assetsType = jsonObject.getString("houseType");
                String weixinNo = jsonObject.getString("weixinNo");
                String gender = jsonObject.getString("gender");
                String birthDay = jsonObject.getString("birthDay");
                String email = jsonObject.getString("email");
                String address = jsonObject.getString("address");
                String offerName = jsonObject.getString("offerName");
                String remark = jsonObject.getString("remark");
                String relationTypeId=jsonObject.getString("relationType");  //与业主关系
                RelationType relationType=EnumUtil.getEnum(RelationType.class,relationTypeId);
                String startTime=jsonObject.getString("startTime");       // 租赁开始时间
                String endTime=jsonObject.getString("endTime");            //租赁结束时间

                if (Objects.isEmpty(mobile) || Objects.isEmpty(houseNo)) {
                    continue;
                }
                FindOne<Resident> find = jdbcSession.findOne(Resident.class)
                        .eq(jsonObject, "id")
                        .eq("mobile", mobile)
                        .eq("deleted", false);
                Resident resident = find.exe();



                //通过查询数据库是否有记录判断是新增还是更新
                if (Objects.isNull(resident)) {
                    List<String> houseIds = new ArrayList<>();
                    houseIds.add(houseNo);
                    resident = Pool.newInstance(Resident.class);
                    //设置住户类型
                    resident.setType(residentType);
                    resident.setRelationType(relationType);

                    //设置租赁开始时间
                    if(Objects.nonEmpty(startTime)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(startTime,df);
                        resident.setStartTime(val.atStartOfDay());
                    }
                    //设置租赁结束时间
                    if(Objects.nonEmpty(endTime)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(endTime,df);
                        resident.setEndTime(val.atStartOfDay());
                    }

                    resident.setRealname(realname);
                    resident.setMobile(mobile);
                    CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                    resident.setCardType(cardTypeEnum);
                    resident.setCardNo(cardNo);
                    if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                        resident.setHouseIds(houseIds);
                    } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                        resident.setShopIds(houseIds);
                    } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                        resident.setParkingIds(houseIds);
                    } else {
                        resident.setHouseIds(houseIds);
                    }
                    resident.setCompanyNo(token.getCompanyNo());

                    //设置额外字段
                    resident.setWeixinNo(weixinNo);
                    if(Objects.nonEmpty(gender)){
                        resident.setGender(Gender.getGender(gender));
                    }
                    if(Objects.nonEmpty(birthDay)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(birthDay,df);
                        resident.setBirthDay(val.atStartOfDay());
                    }
                    resident.setEmail(email);
                    resident.setAddress(address);
                    resident.setOfferName(offerName);
                    resident.setRemark(remark);
                    saveResident(resident);
                } else {
                    List<String> houseIds = new ArrayList<>();
                    houseIds.add(houseNo);
                    //设置住户类型
                    resident.setType(residentType);
                    resident.setRelationType(relationType);

                    //设置租赁开始时间
                    if(Objects.nonEmpty(startTime)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(startTime,df);
                        resident.setStartTime(val.atStartOfDay());
                    }
                    //设置租赁结束时间
                    if(Objects.nonEmpty(endTime)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(endTime,df);
                        resident.setEndTime(val.atStartOfDay());
                    }

                    resident.setRealname(realname);
                    resident.setMobile(mobile);
                    CardType cardTypeEnum = EnumUtil.getEnum(CardType.class, cardType);
                    resident.setCardType(cardTypeEnum);
                    resident.setCardNo(cardNo);
                    if (Objects.equal(HouseType.HOUSE.getId(), assetsType)) {
                        resident.setHouseIds(houseIds);
                        resident.setHouseNo(houseNo);
                    } else if (Objects.equal(HouseType.SHOP.getId(), assetsType)) {
                        resident.setShopIds(houseIds);
                        resident.setShopNo(houseNo);
                    } else if (Objects.equal(HouseType.PARKING.getId(), assetsType)) {
                        resident.setParkingIds(houseIds);
                        resident.setParkingNo(houseNo);
                    } else {
                        resident.setHouseIds(houseIds);
                        resident.setHouseNo(houseNo);
                    }
                    resident.setCompanyNo(token.getCompanyNo());

                    //设置额外字段
                    resident.setWeixinNo(weixinNo);
                    if(Objects.nonEmpty(gender)){
                        resident.setGender(Gender.getGender(gender));
                    }
                    if(Objects.nonEmpty(birthDay)){
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        LocalDate val = LocalDate.parse(birthDay,df);
                        resident.setBirthDay(val.atStartOfDay());
                    }
                    resident.setEmail(email);
                    resident.setAddress(address);
                    resident.setOfferName(offerName);
                    resident.setRemark(remark);

                    updateResident(resident);
                }
            }

        }
        return Result.success();
    }


    /**
     * 批量更新住户房屋中的住户信息
     *
     * @param resident 住户对象
     */
    private void batchUpdateResidentHouse(Resident resident) {
        List<ResidentHouse> list = jdbcSession.findArray(ResidentHouse.class)
                .eq("residentNo", resident.getId())
                .exe();
        list.forEach(item -> {
            item.setAvatar(resident.getAvatar());
            item.setRealname(resident.getRealname());
            item.setMobile(resident.getMobile());
            //如果当前住户房屋是业主,则更新业主下面家属及租客的业主名称
            if (Objects.equal(ResidentType.OWNER.getId(), item.getType().getId())) {
                List<ResidentHouse> otherList = jdbcSession.findArray(ResidentHouse.class)
                        .eq("pid", item.getId())
                        .exe();
                if (Objects.nonEmpty(otherList)) {
                    otherList.forEach(residentHouse -> {
                        residentHouse.setPname(resident.getRealname());
                    });
                    jdbcSession.updateById(otherList);
                }
            }

        });
        jdbcSession.updateById(list);
    }


    @ReqMapping("/getUserListByHouseIds")
    @Override
    public List<ResidentHouse> getUserListByHouseIds(JSONObject jsonObject) throws Exception {
        //获得房屋arr
        JSONArray houseIdArr = jsonObject.getJSONArray("houseIds");
        if(Objects.nonEmpty(houseIdArr)){
            FindArray<ResidentHouse> find = jdbcSession.findArray(ResidentHouse.class);
            find.eq("deleted",false).eq("bindType",BindType.BIND.getId())
                    .in("houseNo",houseIdArr);
            List<ResidentHouse> residentHouseList = find.exe();
            residentHouseList = residentHouseList.stream().collect(Collectors.collectingAndThen(
                    Collectors.toCollection(()->new TreeSet<>(Comparator.comparing(o->o.getResidentNo()))),ArrayList::new));
            return residentHouseList;
        }else{
            return null;
        }
    }



    /**
     * 初始化用户资产绑定编号
     * @param jsonObject
     * @return
     */
    @ReqMapping("/initOwnerNo")
    public Object initOwnerNo(JSONObject jsonObject) {
        List<ResidentHouse>  dbResidentHouseList=jdbcSession.findArray(ResidentHouse.class)
                .isNull("ownerNo")
                .exe(false);
        if(Objects.nonEmpty(dbResidentHouseList)){
            dbResidentHouseList.forEach(v->{
                // 如果数据库中已经存在则取出相应编号
                List<ResidentHouse> residentHouseList =
                        jdbcSession.findArray(ResidentHouse.class).eq("communityNo", v.getCommunityNo()).and().eq("residentNo", v.getResidentNo()).isNotNull("ownerNo").exe(false);
                if (Objects.nonEmpty(residentHouseList)) {
                    ResidentHouse dbData=residentHouseList.get(0);
                    v.setOwnerNo(dbData.getOwnerNo());
                }
                if (Objects.isBlank(v.getOwnerNo())) {
                    SnowflakeIdUtils snowflakeIdUtils = new SnowflakeIdUtils(0);
                    long id = snowflakeIdUtils.nextId();
                    v.setOwnerNo(v.getHouseType().getCode() + id);
                }
                jdbcSession.updateById(v);
            });
        }
        return Result.success();
    }


    /**
     *
     * 根据登录的 token-uuid 获取客户的住户ID
     * @param jsonObject
     * @return
     */
    @ReqMapping("/getFriendResidentNos")
    public List<String> getFriendResidentNos(JSONObject jsonObject){
        String loginId = jsonObject.getString("uuid");

        QueryCondition query = Condition.createQuery(false);
        query.findInSet("users",loginId);
        query.eq("deleted",false);

        return residentUserDao.getFriendResidentNos(query);
    }


    /**
     *
     * 根据登录的管家 token-uuid 获取房屋ID
     * @param jsonObject
     * @return
     */
    @ReqMapping("/getStewardHouseNos")
    public List<String> getStewardHouseNos(JSONObject jsonObject){
        String loginId = jsonObject.getString("uuid");

        QueryCondition query = Condition.createQuery(false);
        query.eq("t1.deleted",false);
        query.findInSet("t1.employeeNos",loginId);
        query.isNotNull("t2.houseNo");

        return residentUserDao.getStewardHouseNos(query);
    }

    /**
     *
     * 根据登录的管家 token-uuid 获取小区
     * @param jsonObject
     * @return
     */
    @ReqMapping("/getStewardCommunity")
    public List<String> getStewardCommunity(JSONObject jsonObject){
        String loginId = jsonObject.getString("uuid");

        QueryCondition query = Condition.createQuery(false);
        query.eq("deleted",false);
        query.findInSet("employee_ids",loginId);

        return residentUserDao.getStewardCommunity(query);
    }



    /**
     * 根据住户ID批量获取住户企微外部信息
     * @param jsonObject
     * @return
     */
    @ReqMapping("/batchResidentExternalInfo")
    public List<Map<String,String>> batchResidentExternalInfo(JSONObject jsonObject){
        JSONArray residentIds = jsonObject.getJSONArray("residentIds");

        QueryCondition query = Condition.createQuery(false);
        query.in("t1.id",residentIds);
        query.eq("deleted",false);
        return residentUserDao.batchResidentExternalInfo(query);
    }


}
